From f4b7fc0da806862802c793c10592f18e3c71c5e0 Mon Sep 17 00:00:00 2001 From: Pino' Surace Date: Fri, 16 Jun 2023 14:27:41 +0200 Subject: [PATCH 01/18] Add prune wasm codes proposal --- docs/proto/proto-docs.md | 30 + proto/cosmwasm/wasm/v1/tx.proto | 23 +- x/wasm/client/cli/gov_tx.go | 46 ++ x/wasm/keeper/keeper.go | 16 + x/wasm/keeper/msg_server.go | 19 + x/wasm/keeper/msg_server_integration_test.go | 80 +++ x/wasm/types/codec.go | 2 + x/wasm/types/tx.go | 30 + x/wasm/types/tx.pb.go | 628 ++++++++++++++++--- x/wasm/types/tx_test.go | 51 +- 10 files changed, 829 insertions(+), 96 deletions(-) diff --git a/docs/proto/proto-docs.md b/docs/proto/proto-docs.md index 9c0cccb887..8b760b8b99 100644 --- a/docs/proto/proto-docs.md +++ b/docs/proto/proto-docs.md @@ -94,6 +94,8 @@ - [MsgMigrateContractResponse](#cosmwasm.wasm.v1.MsgMigrateContractResponse) - [MsgPinCodes](#cosmwasm.wasm.v1.MsgPinCodes) - [MsgPinCodesResponse](#cosmwasm.wasm.v1.MsgPinCodesResponse) + - [MsgPruneWasmCodes](#cosmwasm.wasm.v1.MsgPruneWasmCodes) + - [MsgPruneWasmCodesResponse](#cosmwasm.wasm.v1.MsgPruneWasmCodesResponse) - [MsgStoreAndInstantiateContract](#cosmwasm.wasm.v1.MsgStoreAndInstantiateContract) - [MsgStoreAndInstantiateContractResponse](#cosmwasm.wasm.v1.MsgStoreAndInstantiateContractResponse) - [MsgStoreCode](#cosmwasm.wasm.v1.MsgStoreCode) @@ -1532,6 +1534,33 @@ Since: 0.40 + + +### MsgPruneWasmCodes +MsgPruneWasmCodes is the MsgPruneWasmCodes request type. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `authority` | [string](#string) | | Authority is the address of the governance account. | +| `code_ids` | [uint64](#uint64) | repeated | CodeIDs references the WASM codes | + + + + + + + + +### MsgPruneWasmCodesResponse +MsgPruneWasmCodesResponse defines the response structure for executing a +MsgPruneWasmCodes message. + + + + + + ### MsgStoreAndInstantiateContract @@ -1803,6 +1832,7 @@ Since: 0.40 | | | `StoreAndInstantiateContract` | [MsgStoreAndInstantiateContract](#cosmwasm.wasm.v1.MsgStoreAndInstantiateContract) | [MsgStoreAndInstantiateContractResponse](#cosmwasm.wasm.v1.MsgStoreAndInstantiateContractResponse) | StoreAndInstantiateContract defines a governance operation for storing and instantiating the contract. The authority is defined in the keeper. Since: 0.40 | | +| `PruneWasmCodes` | [MsgPruneWasmCodes](#cosmwasm.wasm.v1.MsgPruneWasmCodes) | [MsgPruneWasmCodesResponse](#cosmwasm.wasm.v1.MsgPruneWasmCodesResponse) | PruneWasmCodes defines a governance operation for pruning a set of code ids in the system. The authority is defined in the keeper. | | diff --git a/proto/cosmwasm/wasm/v1/tx.proto b/proto/cosmwasm/wasm/v1/tx.proto index 90905f5e7d..4e89e78295 100644 --- a/proto/cosmwasm/wasm/v1/tx.proto +++ b/proto/cosmwasm/wasm/v1/tx.proto @@ -60,6 +60,9 @@ service Msg { // Since: 0.40 rpc StoreAndInstantiateContract(MsgStoreAndInstantiateContract) returns (MsgStoreAndInstantiateContractResponse); + // PruneWasmCodes defines a governance operation for pruning a set of + // code ids in the system. The authority is defined in the keeper. + rpc PruneWasmCodes(MsgPruneWasmCodes) returns (MsgPruneWasmCodesResponse); } // MsgStoreCode submit Wasm code to the system @@ -388,4 +391,22 @@ message MsgStoreAndInstantiateContractResponse { string address = 1; // Data contains bytes to returned from the contract bytes data = 2; -} \ No newline at end of file +} + +// MsgPruneWasmCodes is the MsgPruneWasmCodes request type. +message MsgPruneWasmCodes { + option (amino.name) = "wasm/MsgPruneWasmCodes"; + option (cosmos.msg.v1.signer) = "authority"; + + // Authority is the address of the governance account. + string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + // CodeIDs references the WASM codes + repeated uint64 code_ids = 2 [ + (gogoproto.customname) = "CodeIDs", + (gogoproto.moretags) = "yaml:\"code_ids\"" + ]; +} + +// MsgPruneWasmCodesResponse defines the response structure for executing a +// MsgPruneWasmCodes message. +message MsgPruneWasmCodesResponse {} \ No newline at end of file diff --git a/x/wasm/client/cli/gov_tx.go b/x/wasm/client/cli/gov_tx.go index be6114b958..a714c42314 100644 --- a/x/wasm/client/cli/gov_tx.go +++ b/x/wasm/client/cli/gov_tx.go @@ -802,6 +802,52 @@ $ %s tx gov submit-proposal update-instantiate-config 1:nobody 2:everybody 3:%s1 return cmd } +func ProposalPruneWasmCodesCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "prune-wasm-codes [code-ids] --title [text] --summary [text] --authority [address]", + Short: "Submit a prune wasm codes proposal for pruning codes in the system", + Args: cobra.MinimumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, proposalTitle, summary, deposit, err := getProposalInfo(cmd) + if err != nil { + return err + } + authority, err := cmd.Flags().GetString(flagAuthority) + if err != nil { + return fmt.Errorf("authority: %s", err) + } + + if len(authority) == 0 { + return errors.New("authority address is required") + } + + codeIds, err := parsePinCodesArgs(args) + if err != nil { + return err + } + + msg := types.MsgPruneWasmCodes{ + Authority: authority, + CodeIDs: codeIds, + } + + proposalMsg, err := v1.NewMsgSubmitProposal([]sdk.Msg{&msg}, deposit, clientCtx.GetFromAddress().String(), "", proposalTitle, summary) + if err != nil { + return err + } + if err = proposalMsg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), proposalMsg) + }, + SilenceUsage: true, + } + // proposal flags + addCommonProposalFlags(cmd) + return cmd +} + func addCommonProposalFlags(cmd *cobra.Command) { flags.AddTxFlagsToCmd(cmd) cmd.Flags().String(cli.FlagTitle, "", "Title of proposal") diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index b928c1a4ec..ae20ccd594 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -209,6 +209,11 @@ func (k Keeper) storeCodeInfo(ctx sdk.Context, codeID uint64, codeInfo types.Cod store.Set(types.GetCodeKey(codeID), k.cdc.MustMarshal(&codeInfo)) } +func (k Keeper) deleteCodeInfo(ctx sdk.Context, codeID uint64) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.GetCodeKey(codeID)) +} + func (k Keeper) importCode(ctx sdk.Context, codeID uint64, codeInfo types.CodeInfo, wasmCode []byte) error { if ioutils.IsGzip(wasmCode) { var err error @@ -1213,3 +1218,14 @@ func (h DefaultWasmVMContractResponseHandler) Handle(ctx sdk.Context, contractAd } return result, nil } + +// PruneWasmCodes deletes code info for unpinned codes. +func (k Keeper) PruneWasmCodes(ctx sdk.Context, codeIDs []uint64) error { + for _, c := range codeIDs { + if k.IsPinnedCode(ctx, c) { + return errorsmod.Wrap(types.ErrInvalid, fmt.Sprintf("code %d is pinned", c)) + } + k.deleteCodeInfo(ctx, c) + } + return nil +} diff --git a/x/wasm/keeper/msg_server.go b/x/wasm/keeper/msg_server.go index 3c5c3e72e8..ebe4666280 100644 --- a/x/wasm/keeper/msg_server.go +++ b/x/wasm/keeper/msg_server.go @@ -363,3 +363,22 @@ func (m msgServer) selectAuthorizationPolicy(actor string) AuthorizationPolicy { } return DefaultAuthorizationPolicy{} } + +// PruneWasmCodes prunes a set of codeIDs in the system. +func (m msgServer) PruneWasmCodes(goCtx context.Context, req *types.MsgPruneWasmCodes) (*types.MsgPruneWasmCodesResponse, error) { + if err := req.ValidateBasic(); err != nil { + return nil, err + } + authority := m.keeper.GetAuthority() + if authority != req.Authority { + return nil, errorsmod.Wrapf(types.ErrInvalid, "invalid authority; expected %s, got %s", authority, req.Authority) + } + + ctx := sdk.UnwrapSDKContext(goCtx) + err := m.keeper.PruneWasmCodes(ctx, req.CodeIDs) + if err != nil { + return nil, err + } + + return &types.MsgPruneWasmCodesResponse{}, nil +} diff --git a/x/wasm/keeper/msg_server_integration_test.go b/x/wasm/keeper/msg_server_integration_test.go index 69313cf362..2e3cec2e69 100644 --- a/x/wasm/keeper/msg_server_integration_test.go +++ b/x/wasm/keeper/msg_server_integration_test.go @@ -853,3 +853,83 @@ func TestUpdateInstantiateConfig(t *testing.T) { }) } } + +func TestPruneWasmCodes(t *testing.T) { + wasmApp := app.Setup(t) + ctx := wasmApp.BaseApp.NewContext(false, tmproto.Header{}) + + var ( + myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen) + authority = wasmApp.WasmKeeper.GetAuthority() + ) + + specs := map[string]struct { + addr string + pinCode bool + expErr bool + }{ + "authority can prune unpinned code": { + addr: authority, + pinCode: false, + expErr: false, + }, + "authority cannot prune pinned code": { + addr: authority, + pinCode: true, + expErr: true, + }, + "other address cannot prune unpinned code": { + addr: myAddress.String(), + pinCode: false, + expErr: true, + }, + "other address cannot prune pinned code": { + addr: myAddress.String(), + pinCode: true, + expErr: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + // setup + _, _, sender := testdata.KeyTestPubAddr() + msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) { + m.WASMByteCode = wasmContract + m.Sender = sender.String() + }) + + // store code + rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg) + require.NoError(t, err) + var result types.MsgStoreCodeResponse + require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &result)) + + if spec.pinCode { + // pin code + msgPin := &types.MsgPinCodes{ + Authority: authority, + CodeIDs: []uint64{result.CodeID}, + } + _, err = wasmApp.MsgServiceRouter().Handler(msgPin)(ctx, msgPin) + require.NoError(t, err) + assert.True(t, wasmApp.WasmKeeper.IsPinnedCode(ctx, result.CodeID)) + } + + // when + msgPruneCodes := &types.MsgPruneWasmCodes{ + Authority: spec.addr, + CodeIDs: []uint64{result.CodeID}, + } + _, err = wasmApp.MsgServiceRouter().Handler(msgPruneCodes)(ctx, msgPruneCodes) + + // then + if spec.expErr { + require.Error(t, err) + assert.NotNil(t, wasmApp.WasmKeeper.GetCodeInfo(ctx, result.CodeID)) + } else { + require.NoError(t, err) + assert.Nil(t, wasmApp.WasmKeeper.GetCodeInfo(ctx, result.CodeID)) + } + }) + } +} diff --git a/x/wasm/types/codec.go b/x/wasm/types/codec.go index 10ff3af67d..edcaf8aa08 100644 --- a/x/wasm/types/codec.go +++ b/x/wasm/types/codec.go @@ -28,6 +28,7 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgPinCodes{}, "wasm/MsgPinCodes", nil) cdc.RegisterConcrete(&MsgUnpinCodes{}, "wasm/MsgUnpinCodes", nil) cdc.RegisterConcrete(&MsgStoreAndInstantiateContract{}, "wasm/MsgStoreAndInstantiateContract", nil) + cdc.RegisterConcrete(&MsgPruneWasmCodes{}, "wasm/MsgPruneWasmCodes", nil) cdc.RegisterConcrete(&PinCodesProposal{}, "wasm/PinCodesProposal", nil) cdc.RegisterConcrete(&UnpinCodesProposal{}, "wasm/UnpinCodesProposal", nil) @@ -76,6 +77,7 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { &MsgPinCodes{}, &MsgUnpinCodes{}, &MsgStoreAndInstantiateContract{}, + &MsgPruneWasmCodes{}, ) registry.RegisterImplementations( (*v1beta1.Content)(nil), diff --git a/x/wasm/types/tx.go b/x/wasm/types/tx.go index d75993b7f6..90f636ae8b 100644 --- a/x/wasm/types/tx.go +++ b/x/wasm/types/tx.go @@ -615,3 +615,33 @@ func (msg MsgStoreAndInstantiateContract) ValidateBasic() error { } return nil } + +func (msg MsgPruneWasmCodes) Route() string { + return RouterKey +} + +func (msg MsgPruneWasmCodes) Type() string { + return "prune-wasm-codes" +} + +func (msg MsgPruneWasmCodes) GetSigners() []sdk.AccAddress { + authority, err := sdk.AccAddressFromBech32(msg.Authority) + if err != nil { // should never happen as valid basic rejects invalid addresses + panic(err.Error()) + } + return []sdk.AccAddress{authority} +} + +func (msg MsgPruneWasmCodes) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg)) +} + +func (msg MsgPruneWasmCodes) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil { + return errorsmod.Wrap(err, "authority") + } + if len(msg.CodeIDs) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "empty code ids") + } + return nil +} diff --git a/x/wasm/types/tx.pb.go b/x/wasm/types/tx.pb.go index 4d4ad490e2..41df23f309 100644 --- a/x/wasm/types/tx.pb.go +++ b/x/wasm/types/tx.pb.go @@ -1289,6 +1289,94 @@ func (m *MsgStoreAndInstantiateContractResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgStoreAndInstantiateContractResponse proto.InternalMessageInfo +// MsgPruneWasmCodes is the MsgPruneWasmCodes request type. +type MsgPruneWasmCodes struct { + // Authority is the address of the governance account. + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + // CodeIDs references the WASM codes + CodeIDs []uint64 `protobuf:"varint,2,rep,packed,name=code_ids,json=codeIds,proto3" json:"code_ids,omitempty" yaml:"code_ids"` +} + +func (m *MsgPruneWasmCodes) Reset() { *m = MsgPruneWasmCodes{} } +func (m *MsgPruneWasmCodes) String() string { return proto.CompactTextString(m) } +func (*MsgPruneWasmCodes) ProtoMessage() {} +func (*MsgPruneWasmCodes) Descriptor() ([]byte, []int) { + return fileDescriptor_4f74d82755520264, []int{26} +} + +func (m *MsgPruneWasmCodes) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} + +func (m *MsgPruneWasmCodes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgPruneWasmCodes.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 *MsgPruneWasmCodes) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgPruneWasmCodes.Merge(m, src) +} + +func (m *MsgPruneWasmCodes) XXX_Size() int { + return m.Size() +} + +func (m *MsgPruneWasmCodes) XXX_DiscardUnknown() { + xxx_messageInfo_MsgPruneWasmCodes.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgPruneWasmCodes proto.InternalMessageInfo + +// MsgPruneWasmCodesResponse defines the response structure for executing a +// MsgPruneWasmCodes message. +type MsgPruneWasmCodesResponse struct{} + +func (m *MsgPruneWasmCodesResponse) Reset() { *m = MsgPruneWasmCodesResponse{} } +func (m *MsgPruneWasmCodesResponse) String() string { return proto.CompactTextString(m) } +func (*MsgPruneWasmCodesResponse) ProtoMessage() {} +func (*MsgPruneWasmCodesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_4f74d82755520264, []int{27} +} + +func (m *MsgPruneWasmCodesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} + +func (m *MsgPruneWasmCodesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgPruneWasmCodesResponse.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 *MsgPruneWasmCodesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgPruneWasmCodesResponse.Merge(m, src) +} + +func (m *MsgPruneWasmCodesResponse) XXX_Size() int { + return m.Size() +} + +func (m *MsgPruneWasmCodesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgPruneWasmCodesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgPruneWasmCodesResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgStoreCode)(nil), "cosmwasm.wasm.v1.MsgStoreCode") proto.RegisterType((*MsgStoreCodeResponse)(nil), "cosmwasm.wasm.v1.MsgStoreCodeResponse") @@ -1316,103 +1404,108 @@ func init() { proto.RegisterType((*MsgUnpinCodesResponse)(nil), "cosmwasm.wasm.v1.MsgUnpinCodesResponse") proto.RegisterType((*MsgStoreAndInstantiateContract)(nil), "cosmwasm.wasm.v1.MsgStoreAndInstantiateContract") proto.RegisterType((*MsgStoreAndInstantiateContractResponse)(nil), "cosmwasm.wasm.v1.MsgStoreAndInstantiateContractResponse") + proto.RegisterType((*MsgPruneWasmCodes)(nil), "cosmwasm.wasm.v1.MsgPruneWasmCodes") + proto.RegisterType((*MsgPruneWasmCodesResponse)(nil), "cosmwasm.wasm.v1.MsgPruneWasmCodesResponse") } func init() { proto.RegisterFile("cosmwasm/wasm/v1/tx.proto", fileDescriptor_4f74d82755520264) } var fileDescriptor_4f74d82755520264 = []byte{ - // 1441 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x58, 0xcf, 0x6f, 0x1b, 0xc5, - 0x17, 0xcf, 0xc6, 0xbf, 0x5f, 0xfc, 0x6d, 0xd3, 0xad, 0x9b, 0x6c, 0xb6, 0xad, 0x9d, 0x6e, 0x7f, - 0xb9, 0xfd, 0xb6, 0x76, 0x63, 0xa0, 0x82, 0x70, 0x8a, 0x53, 0x24, 0x52, 0xc9, 0x10, 0x6d, 0xd4, - 0x56, 0xa0, 0x4a, 0xd6, 0xda, 0x3b, 0xd9, 0xac, 0x9a, 0xdd, 0x35, 0x9e, 0x75, 0x93, 0x1c, 0xb8, - 0x80, 0x84, 0x04, 0x27, 0xfe, 0x09, 0x24, 0xe0, 0x42, 0x0f, 0x20, 0x71, 0xec, 0xb1, 0x12, 0x97, - 0x8a, 0x13, 0xa7, 0x00, 0x2e, 0x52, 0xb9, 0x21, 0x71, 0xe4, 0x84, 0x66, 0x66, 0x77, 0x3d, 0x5e, - 0xef, 0x3a, 0x4e, 0x4a, 0xc5, 0x81, 0x4b, 0xb2, 0x33, 0xef, 0xc7, 0xbc, 0xcf, 0xe7, 0xbd, 0x99, - 0x79, 0x63, 0x58, 0x68, 0x3b, 0xd8, 0xda, 0xd1, 0xb0, 0x55, 0xa5, 0x7f, 0x1e, 0x2e, 0x55, 0xdd, - 0xdd, 0x4a, 0xa7, 0xeb, 0xb8, 0x8e, 0x38, 0xeb, 0x8b, 0x2a, 0xf4, 0xcf, 0xc3, 0x25, 0xb9, 0x48, - 0x66, 0x1c, 0x5c, 0x6d, 0x69, 0x18, 0x55, 0x1f, 0x2e, 0xb5, 0x90, 0xab, 0x2d, 0x55, 0xdb, 0x8e, - 0x69, 0x33, 0x0b, 0x79, 0xde, 0x93, 0x5b, 0xd8, 0x20, 0x9e, 0x2c, 0x6c, 0x78, 0x82, 0x82, 0xe1, - 0x18, 0x0e, 0xfd, 0xac, 0x92, 0x2f, 0x6f, 0xf6, 0xcc, 0xe8, 0xda, 0x7b, 0x1d, 0x84, 0x3d, 0xe9, - 0x02, 0x73, 0xd6, 0x64, 0x66, 0x6c, 0xe0, 0x89, 0x4e, 0x68, 0x96, 0x69, 0x3b, 0x55, 0xfa, 0x97, - 0x4d, 0x29, 0xbf, 0x09, 0x90, 0x6f, 0x60, 0x63, 0xc3, 0x75, 0xba, 0x68, 0xd5, 0xd1, 0x91, 0x38, - 0x07, 0x69, 0x8c, 0x6c, 0x1d, 0x75, 0x25, 0x61, 0x51, 0x28, 0xe7, 0x54, 0x6f, 0x24, 0xde, 0x84, - 0x63, 0x64, 0xb5, 0x66, 0x6b, 0xcf, 0x45, 0xcd, 0xb6, 0xa3, 0x23, 0x69, 0x7a, 0x51, 0x28, 0xe7, - 0xeb, 0xb3, 0xfd, 0xfd, 0x52, 0xfe, 0xde, 0xca, 0x46, 0xa3, 0xbe, 0xe7, 0x52, 0x0f, 0x6a, 0x9e, - 0xe8, 0xf9, 0x23, 0xf1, 0x0e, 0xcc, 0x99, 0x36, 0x76, 0x35, 0xdb, 0x35, 0x35, 0x17, 0x35, 0x3b, - 0xa8, 0x6b, 0x99, 0x18, 0x9b, 0x8e, 0x2d, 0xa5, 0x16, 0x85, 0xf2, 0x4c, 0xad, 0x58, 0x09, 0xd3, - 0x55, 0x59, 0x69, 0xb7, 0x11, 0xc6, 0xab, 0x8e, 0xbd, 0x69, 0x1a, 0xea, 0x29, 0xce, 0x7a, 0x3d, - 0x30, 0x5e, 0x3e, 0xf7, 0xd1, 0xf3, 0x47, 0x57, 0xbd, 0xd8, 0x3e, 0x7b, 0xfe, 0xe8, 0xea, 0x09, - 0x4a, 0x05, 0x8f, 0xe4, 0x76, 0x32, 0x9b, 0x98, 0x4d, 0xde, 0x4e, 0x66, 0x93, 0xb3, 0x29, 0xe5, - 0x1e, 0x14, 0x78, 0x99, 0x8a, 0x70, 0xc7, 0xb1, 0x31, 0x12, 0xcf, 0x43, 0x86, 0x60, 0x69, 0x9a, - 0x3a, 0x85, 0x9b, 0xac, 0x43, 0x7f, 0xbf, 0x94, 0x26, 0x2a, 0x6b, 0xb7, 0xd4, 0x34, 0x11, 0xad, - 0xe9, 0xa2, 0x0c, 0xd9, 0xf6, 0x16, 0x6a, 0x3f, 0xc0, 0x3d, 0x8b, 0x81, 0x56, 0x83, 0xb1, 0xf2, - 0x78, 0x1a, 0xe6, 0x1a, 0xd8, 0x58, 0x1b, 0x04, 0xb9, 0xea, 0xd8, 0x6e, 0x57, 0x6b, 0xbb, 0xb1, - 0x4c, 0x16, 0x20, 0xa5, 0xe9, 0x96, 0x69, 0x53, 0x5f, 0x39, 0x95, 0x0d, 0xf8, 0x48, 0x12, 0xb1, - 0x91, 0x14, 0x20, 0xb5, 0xad, 0xb5, 0xd0, 0xb6, 0x94, 0x64, 0xa6, 0x74, 0x20, 0x96, 0x21, 0x61, - 0x61, 0x83, 0xf2, 0x99, 0xaf, 0xcf, 0xfd, 0xb5, 0x5f, 0x12, 0x55, 0x6d, 0xc7, 0x0f, 0xa3, 0x81, - 0x30, 0xd6, 0x0c, 0xa4, 0x12, 0x15, 0x71, 0x13, 0x52, 0x9b, 0x3d, 0x5b, 0xc7, 0x52, 0x7a, 0x31, - 0x51, 0x9e, 0xa9, 0x2d, 0x54, 0xbc, 0xf2, 0x20, 0x85, 0x59, 0xf1, 0x0a, 0xb3, 0xb2, 0xea, 0x98, - 0x76, 0xfd, 0xb5, 0x27, 0xfb, 0xa5, 0xa9, 0xaf, 0x7f, 0x2e, 0x95, 0x0d, 0xd3, 0xdd, 0xea, 0xb5, - 0x2a, 0x6d, 0xc7, 0xf2, 0x6a, 0xc9, 0xfb, 0x77, 0x1d, 0xeb, 0x0f, 0xbc, 0xba, 0x23, 0x06, 0xf8, - 0xcb, 0xe7, 0x8f, 0xae, 0x0a, 0x2a, 0x73, 0xbf, 0xfc, 0xff, 0x50, 0x76, 0x4e, 0xfb, 0xd9, 0x89, - 0xe0, 0x49, 0x79, 0x07, 0x8a, 0xd1, 0x92, 0x20, 0x4b, 0x12, 0x64, 0x34, 0x5d, 0xef, 0x22, 0x8c, - 0x3d, 0x2a, 0xfd, 0xa1, 0x28, 0x42, 0x52, 0xd7, 0x5c, 0xcd, 0x4b, 0x0b, 0xfd, 0x56, 0xfe, 0x98, - 0x86, 0xf9, 0x68, 0x87, 0xb5, 0xff, 0x70, 0x4e, 0x08, 0x55, 0x58, 0xdb, 0x76, 0xa5, 0x0c, 0xa3, - 0x8a, 0x7c, 0x8b, 0xf3, 0x90, 0xd9, 0x34, 0x77, 0x9b, 0x24, 0xd2, 0xec, 0xa2, 0x50, 0xce, 0xaa, - 0xe9, 0x4d, 0x73, 0xb7, 0x81, 0x8d, 0xe5, 0x6b, 0xa1, 0x04, 0x9e, 0x19, 0x93, 0xc0, 0x9a, 0xf2, - 0x2e, 0x94, 0x62, 0x44, 0x47, 0x4c, 0xe1, 0xc7, 0xd3, 0x20, 0x36, 0xb0, 0xf1, 0xd6, 0x2e, 0x6a, - 0xf7, 0x26, 0xd8, 0x51, 0x64, 0x83, 0x7a, 0x3a, 0x5e, 0x02, 0x83, 0xb1, 0x9f, 0x88, 0xc4, 0x21, - 0x12, 0x91, 0x7a, 0xb9, 0x9b, 0xe3, 0x72, 0x88, 0xdb, 0x79, 0x9f, 0xdb, 0x10, 0x5c, 0xe5, 0x06, - 0xc8, 0xa3, 0xb3, 0x01, 0xa3, 0x3e, 0x6f, 0x02, 0xc7, 0xdb, 0x63, 0x81, 0xf2, 0xd6, 0x30, 0x8d, - 0xae, 0xf6, 0x82, 0xbc, 0x4d, 0x54, 0xfb, 0x1e, 0xb9, 0xc9, 0x03, 0xc9, 0x8d, 0x07, 0x1d, 0x8a, - 0xd5, 0x03, 0x1d, 0x9a, 0x1d, 0x0b, 0xfa, 0x13, 0x01, 0x8e, 0x35, 0xb0, 0x71, 0xa7, 0xa3, 0x6b, - 0x2e, 0x5a, 0xa1, 0x1b, 0x37, 0x0e, 0xf0, 0x69, 0xc8, 0xd9, 0x68, 0xa7, 0xc9, 0x6f, 0xf5, 0xac, - 0x8d, 0x76, 0x98, 0x11, 0xcf, 0x46, 0x62, 0x98, 0x8d, 0xe5, 0xf3, 0xa1, 0xf0, 0x4f, 0xfa, 0xe1, - 0x73, 0xab, 0x2a, 0x12, 0xbd, 0x0a, 0xb8, 0x19, 0x3f, 0x6c, 0xc5, 0x80, 0xff, 0x35, 0xb0, 0xb1, - 0xba, 0x8d, 0xb4, 0xee, 0xf8, 0x00, 0xc7, 0xc5, 0xa0, 0x84, 0x62, 0x10, 0xfd, 0x18, 0x06, 0x7e, - 0x95, 0x79, 0x38, 0x35, 0x34, 0x11, 0x44, 0xf0, 0xbb, 0x40, 0x79, 0x65, 0xc1, 0x0d, 0xef, 0xd4, - 0x4d, 0xd3, 0x88, 0x8d, 0x87, 0xab, 0x82, 0xe9, 0xd8, 0x2a, 0xb8, 0x0f, 0x32, 0x61, 0x35, 0xe6, - 0x9a, 0x4f, 0x4c, 0x74, 0xcd, 0x4b, 0x36, 0xda, 0x59, 0x8b, 0xbc, 0xe9, 0xab, 0x21, 0xd8, 0xa5, - 0x61, 0xea, 0x47, 0xb0, 0x28, 0x17, 0x40, 0x89, 0x97, 0x06, 0x84, 0x7c, 0x23, 0xc0, 0xf1, 0x40, - 0x6d, 0x5d, 0xeb, 0x6a, 0x16, 0x16, 0x6f, 0x42, 0x4e, 0xeb, 0xb9, 0x5b, 0x4e, 0xd7, 0x74, 0xf7, - 0x18, 0x11, 0x75, 0xe9, 0xc7, 0x6f, 0xaf, 0x17, 0xbc, 0x83, 0x60, 0x85, 0x9d, 0x58, 0x1b, 0x6e, - 0xd7, 0xb4, 0x0d, 0x75, 0xa0, 0x2a, 0xbe, 0x09, 0xe9, 0x0e, 0xf5, 0x40, 0x49, 0x9a, 0xa9, 0x49, - 0xa3, 0x60, 0xd9, 0x0a, 0xf5, 0x1c, 0x39, 0x39, 0xd8, 0x69, 0xe0, 0x99, 0xb0, 0x9d, 0x31, 0x70, - 0x46, 0x20, 0x16, 0x86, 0x21, 0x32, 0x5b, 0x65, 0x81, 0x5e, 0x6b, 0xfc, 0x54, 0x00, 0xe6, 0x7b, - 0x06, 0x66, 0xa3, 0xa7, 0x3b, 0xc1, 0xa6, 0x3f, 0x2a, 0x98, 0x7f, 0xe4, 0x30, 0x1d, 0x8b, 0x8a, - 0x0f, 0x53, 0xb9, 0x4e, 0x51, 0xf1, 0x53, 0x63, 0x37, 0xfb, 0x17, 0x02, 0xcc, 0x34, 0xb0, 0xb1, - 0x6e, 0xda, 0xa4, 0x08, 0x8f, 0x9e, 0xb2, 0x37, 0x08, 0x4a, 0x5a, 0xd8, 0x24, 0x69, 0x89, 0x72, - 0xb2, 0x5e, 0xec, 0xef, 0x97, 0x32, 0xac, 0xb2, 0xf1, 0x9f, 0xfb, 0xa5, 0xe3, 0x7b, 0x9a, 0xb5, - 0xbd, 0xac, 0xf8, 0x4a, 0x8a, 0x9a, 0x61, 0xd5, 0x8e, 0xd9, 0x59, 0x30, 0x0c, 0x6d, 0xd6, 0x87, - 0xe6, 0xc7, 0xa5, 0x9c, 0x82, 0x93, 0xdc, 0x30, 0x48, 0xd4, 0x57, 0x02, 0x3d, 0x09, 0xee, 0xd8, - 0x9d, 0x7f, 0x11, 0xc0, 0xc5, 0x51, 0x00, 0xc1, 0x59, 0x32, 0x88, 0xcc, 0x3b, 0x4b, 0x06, 0x13, - 0x01, 0x88, 0x1f, 0x92, 0xb4, 0x63, 0xa3, 0xdd, 0xf4, 0x8a, 0xad, 0x47, 0xf5, 0xbe, 0x47, 0x45, - 0x35, 0xfa, 0xca, 0x48, 0xbc, 0xe0, 0x2b, 0x23, 0xf9, 0x02, 0xaf, 0x0c, 0xf1, 0x2c, 0x40, 0x8f, - 0xe0, 0x67, 0xa1, 0xa4, 0x68, 0x8b, 0x94, 0xeb, 0xf9, 0x8c, 0x0c, 0xba, 0xc6, 0x34, 0xdf, 0x35, - 0x06, 0x0d, 0x61, 0x26, 0xa2, 0x21, 0xcc, 0x1e, 0xa2, 0x0f, 0xc9, 0xbd, 0xdc, 0x86, 0x90, 0x9c, - 0xf9, 0x4e, 0xaf, 0xdb, 0x46, 0x12, 0x78, 0x67, 0x3e, 0x1d, 0x91, 0x56, 0xad, 0xd5, 0x33, 0xb7, - 0xc9, 0x65, 0x30, 0xc3, 0x5a, 0x35, 0x6f, 0x48, 0xae, 0x4f, 0x5a, 0x4e, 0x5b, 0x1a, 0xde, 0x92, - 0xf2, 0xde, 0x4b, 0xc8, 0xd1, 0xd1, 0xdb, 0x1a, 0xde, 0x5a, 0xbe, 0x39, 0x5a, 0x55, 0xe7, 0x87, - 0x1e, 0x65, 0xd1, 0xa5, 0xa2, 0xdc, 0x85, 0x4b, 0xe3, 0x35, 0x8e, 0xd6, 0x43, 0xd6, 0xbe, 0x03, - 0x48, 0x34, 0xb0, 0x21, 0x6e, 0x40, 0x6e, 0xf0, 0xba, 0x8d, 0xa8, 0x03, 0xfe, 0x5d, 0x28, 0x5f, - 0x1a, 0x2f, 0x0f, 0x42, 0xf9, 0x00, 0x4e, 0x46, 0x95, 0x7d, 0x39, 0xd2, 0x3c, 0x42, 0x53, 0xbe, - 0x31, 0xa9, 0x66, 0xb0, 0xa4, 0x0b, 0x85, 0xc8, 0x27, 0xcd, 0x95, 0x49, 0x3d, 0xd5, 0xe4, 0xa5, - 0x89, 0x55, 0x83, 0x55, 0x11, 0x1c, 0x0f, 0x77, 0xe1, 0x17, 0x22, 0xbd, 0x84, 0xb4, 0xe4, 0x6b, - 0x93, 0x68, 0xf1, 0xcb, 0x84, 0x9b, 0xd6, 0xe8, 0x65, 0x42, 0x5a, 0x31, 0xcb, 0xc4, 0xb5, 0x8f, - 0xef, 0xc1, 0x0c, 0xdf, 0x26, 0x2e, 0x46, 0x1a, 0x73, 0x1a, 0x72, 0xf9, 0x20, 0x8d, 0xc0, 0xf5, - 0x5d, 0x00, 0xae, 0xbf, 0x2b, 0x45, 0xda, 0x0d, 0x14, 0xe4, 0xcb, 0x07, 0x28, 0x04, 0x7e, 0x3f, - 0x84, 0xf9, 0xb8, 0xa6, 0xed, 0xda, 0x98, 0xe0, 0x46, 0xb4, 0xe5, 0x57, 0x0f, 0xa3, 0x1d, 0x2c, - 0x7f, 0x1f, 0xf2, 0x43, 0x2d, 0xd2, 0xb9, 0x31, 0x5e, 0x98, 0x8a, 0x7c, 0xe5, 0x40, 0x15, 0xde, - 0xfb, 0x50, 0xcf, 0x12, 0xed, 0x9d, 0x57, 0x89, 0xf1, 0x1e, 0xd9, 0x3f, 0xac, 0x43, 0x36, 0xe8, - 0x13, 0xce, 0x46, 0x9a, 0xf9, 0x62, 0xf9, 0xe2, 0x58, 0x31, 0x9f, 0x64, 0xee, 0xea, 0x8e, 0x4e, - 0xf2, 0x40, 0x21, 0x26, 0xc9, 0xa3, 0x37, 0xaa, 0xf8, 0xa9, 0x00, 0xa7, 0xc7, 0x5d, 0xa7, 0x37, - 0xe2, 0x8f, 0xa5, 0x68, 0x0b, 0xf9, 0xf5, 0xc3, 0x5a, 0xf8, 0xb1, 0xd4, 0x6f, 0x3d, 0xf9, 0xb5, - 0x38, 0xf5, 0xa4, 0x5f, 0x14, 0x9e, 0xf6, 0x8b, 0xc2, 0x2f, 0xfd, 0xa2, 0xf0, 0xf9, 0xb3, 0xe2, - 0xd4, 0xd3, 0x67, 0xc5, 0xa9, 0x9f, 0x9e, 0x15, 0xa7, 0xde, 0xbf, 0xc4, 0x5d, 0x35, 0xab, 0x0e, - 0xb6, 0xee, 0xf9, 0x3f, 0x43, 0xea, 0xd5, 0x5d, 0xf6, 0x73, 0x24, 0xbd, 0x6e, 0x5a, 0x69, 0xfa, - 0xf3, 0xe2, 0x2b, 0x7f, 0x07, 0x00, 0x00, 0xff, 0xff, 0xe9, 0x52, 0x18, 0xa3, 0x28, 0x15, 0x00, - 0x00, + // 1493 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x58, 0xcd, 0x6f, 0xdb, 0xc6, + 0x12, 0x37, 0xad, 0xef, 0x91, 0x5e, 0xe2, 0x30, 0x8a, 0x4d, 0xd3, 0x89, 0xe4, 0xd0, 0xf9, 0x50, + 0xbe, 0xa4, 0x58, 0xef, 0xbd, 0xa0, 0x75, 0x4f, 0x96, 0x53, 0xa0, 0x0e, 0xa0, 0xd6, 0xa0, 0x91, + 0x18, 0x2d, 0x02, 0x08, 0x94, 0xb8, 0xa6, 0x89, 0x98, 0xa4, 0xca, 0xa5, 0x62, 0xfb, 0xd0, 0x4b, + 0x0b, 0x14, 0x68, 0x4f, 0xbd, 0xf6, 0x0f, 0x28, 0xd0, 0xf6, 0xd2, 0x14, 0xe8, 0xa1, 0xc7, 0x1c, + 0x03, 0xf4, 0x12, 0xf4, 0xd4, 0x93, 0xdb, 0x3a, 0x05, 0xd2, 0x5b, 0x81, 0x1e, 0x7b, 0x2a, 0x76, + 0x97, 0xa4, 0x28, 0x8a, 0x94, 0x65, 0xa7, 0x41, 0x0e, 0xbd, 0xd8, 0xdc, 0xdd, 0x99, 0xd9, 0xf9, + 0xfd, 0x66, 0x76, 0x76, 0x56, 0x30, 0xdb, 0xb1, 0xb0, 0xb1, 0xa3, 0x60, 0xa3, 0x46, 0xff, 0x3c, + 0x5c, 0xac, 0x39, 0xbb, 0xd5, 0xae, 0x6d, 0x39, 0x16, 0x3f, 0xe5, 0x2d, 0x55, 0xe9, 0x9f, 0x87, + 0x8b, 0x62, 0x89, 0xcc, 0x58, 0xb8, 0xd6, 0x56, 0x30, 0xaa, 0x3d, 0x5c, 0x6c, 0x23, 0x47, 0x59, + 0xac, 0x75, 0x2c, 0xdd, 0x64, 0x1a, 0xe2, 0x8c, 0xbb, 0x6e, 0x60, 0x8d, 0x58, 0x32, 0xb0, 0xe6, + 0x2e, 0x14, 0x35, 0x4b, 0xb3, 0xe8, 0x67, 0x8d, 0x7c, 0xb9, 0xb3, 0x67, 0x87, 0xf7, 0xde, 0xeb, + 0x22, 0xec, 0xae, 0xce, 0x32, 0x63, 0x2d, 0xa6, 0xc6, 0x06, 0xee, 0xd2, 0x29, 0xc5, 0xd0, 0x4d, + 0xab, 0x46, 0xff, 0xb2, 0x29, 0xe9, 0x37, 0x0e, 0x0a, 0x4d, 0xac, 0xad, 0x3b, 0x96, 0x8d, 0x56, + 0x2c, 0x15, 0xf1, 0xd3, 0x90, 0xc6, 0xc8, 0x54, 0x91, 0x2d, 0x70, 0xf3, 0x5c, 0x25, 0x27, 0xbb, + 0x23, 0xfe, 0x16, 0x9c, 0x20, 0xbb, 0xb5, 0xda, 0x7b, 0x0e, 0x6a, 0x75, 0x2c, 0x15, 0x09, 0x93, + 0xf3, 0x5c, 0xa5, 0xd0, 0x98, 0x3a, 0xd8, 0x2f, 0x17, 0x36, 0x96, 0xd7, 0x9b, 0x8d, 0x3d, 0x87, + 0x5a, 0x90, 0x0b, 0x44, 0xce, 0x1b, 0xf1, 0x77, 0x61, 0x5a, 0x37, 0xb1, 0xa3, 0x98, 0x8e, 0xae, + 0x38, 0xa8, 0xd5, 0x45, 0xb6, 0xa1, 0x63, 0xac, 0x5b, 0xa6, 0x90, 0x9a, 0xe7, 0x2a, 0xf9, 0x7a, + 0xa9, 0x1a, 0xa6, 0xab, 0xba, 0xdc, 0xe9, 0x20, 0x8c, 0x57, 0x2c, 0x73, 0x53, 0xd7, 0xe4, 0x33, + 0x01, 0xed, 0x35, 0x5f, 0x79, 0xe9, 0xfc, 0x87, 0xcf, 0x1f, 0x5d, 0x75, 0x7d, 0xfb, 0xf4, 0xf9, + 0xa3, 0xab, 0xa7, 0x28, 0x15, 0x41, 0x24, 0x77, 0x92, 0xd9, 0xc4, 0x54, 0xf2, 0x4e, 0x32, 0x9b, + 0x9c, 0x4a, 0x49, 0x1b, 0x50, 0x0c, 0xae, 0xc9, 0x08, 0x77, 0x2d, 0x13, 0x23, 0x7e, 0x01, 0x32, + 0x04, 0x4b, 0x4b, 0x57, 0x29, 0xdc, 0x64, 0x03, 0x0e, 0xf6, 0xcb, 0x69, 0x22, 0xb2, 0x7a, 0x5b, + 0x4e, 0x93, 0xa5, 0x55, 0x95, 0x17, 0x21, 0xdb, 0xd9, 0x42, 0x9d, 0x07, 0xb8, 0x67, 0x30, 0xd0, + 0xb2, 0x3f, 0x96, 0x1e, 0x4f, 0xc2, 0x74, 0x13, 0x6b, 0xab, 0x7d, 0x27, 0x57, 0x2c, 0xd3, 0xb1, + 0x95, 0x8e, 0x13, 0xcb, 0x64, 0x11, 0x52, 0x8a, 0x6a, 0xe8, 0x26, 0xb5, 0x95, 0x93, 0xd9, 0x20, + 0xe8, 0x49, 0x22, 0xd6, 0x93, 0x22, 0xa4, 0xb6, 0x95, 0x36, 0xda, 0x16, 0x92, 0x4c, 0x95, 0x0e, + 0xf8, 0x0a, 0x24, 0x0c, 0xac, 0x51, 0x3e, 0x0b, 0x8d, 0xe9, 0xbf, 0xf6, 0xcb, 0xbc, 0xac, 0xec, + 0x78, 0x6e, 0x34, 0x11, 0xc6, 0x8a, 0x86, 0x64, 0x22, 0xc2, 0x6f, 0x42, 0x6a, 0xb3, 0x67, 0xaa, + 0x58, 0x48, 0xcf, 0x27, 0x2a, 0xf9, 0xfa, 0x6c, 0xd5, 0x4d, 0x0f, 0x92, 0x98, 0x55, 0x37, 0x31, + 0xab, 0x2b, 0x96, 0x6e, 0x36, 0xfe, 0xff, 0x64, 0xbf, 0x3c, 0xf1, 0xf5, 0xcf, 0xe5, 0x8a, 0xa6, + 0x3b, 0x5b, 0xbd, 0x76, 0xb5, 0x63, 0x19, 0x6e, 0x2e, 0xb9, 0xff, 0x6e, 0x60, 0xf5, 0x81, 0x9b, + 0x77, 0x44, 0x01, 0x7f, 0xf9, 0xfc, 0xd1, 0x55, 0x4e, 0x66, 0xe6, 0x97, 0xae, 0x85, 0xa2, 0x33, + 0xe7, 0x45, 0x27, 0x82, 0x27, 0xe9, 0x6d, 0x28, 0x45, 0xaf, 0xf8, 0x51, 0x12, 0x20, 0xa3, 0xa8, + 0xaa, 0x8d, 0x30, 0x76, 0xa9, 0xf4, 0x86, 0x3c, 0x0f, 0x49, 0x55, 0x71, 0x14, 0x37, 0x2c, 0xf4, + 0x5b, 0xfa, 0x63, 0x12, 0x66, 0xa2, 0x0d, 0xd6, 0xff, 0xc5, 0x31, 0x21, 0x54, 0x61, 0x65, 0xdb, + 0x11, 0x32, 0x8c, 0x2a, 0xf2, 0xcd, 0xcf, 0x40, 0x66, 0x53, 0xdf, 0x6d, 0x11, 0x4f, 0xb3, 0xf3, + 0x5c, 0x25, 0x2b, 0xa7, 0x37, 0xf5, 0xdd, 0x26, 0xd6, 0x96, 0xae, 0x87, 0x02, 0x78, 0x76, 0x44, + 0x00, 0xeb, 0xd2, 0x3b, 0x50, 0x8e, 0x59, 0x3a, 0x66, 0x08, 0x3f, 0x9a, 0x04, 0xbe, 0x89, 0xb5, + 0x37, 0x77, 0x51, 0xa7, 0x37, 0xc6, 0x89, 0x22, 0x07, 0xd4, 0x95, 0x71, 0x03, 0xe8, 0x8f, 0xbd, + 0x40, 0x24, 0x8e, 0x10, 0x88, 0xd4, 0xcb, 0x3d, 0x1c, 0x97, 0x43, 0xdc, 0xce, 0x78, 0xdc, 0x86, + 0xe0, 0x4a, 0x37, 0x41, 0x1c, 0x9e, 0xf5, 0x19, 0xf5, 0x78, 0xe3, 0x02, 0xbc, 0x3d, 0xe6, 0x28, + 0x6f, 0x4d, 0x5d, 0xb3, 0x95, 0x17, 0xe4, 0x6d, 0xac, 0xdc, 0x77, 0xc9, 0x4d, 0x1e, 0x4a, 0x6e, + 0x3c, 0xe8, 0x90, 0xaf, 0x2e, 0xe8, 0xd0, 0xec, 0x48, 0xd0, 0x1f, 0x73, 0x70, 0xa2, 0x89, 0xb5, + 0xbb, 0x5d, 0x55, 0x71, 0xd0, 0x32, 0x3d, 0xb8, 0x71, 0x80, 0xe7, 0x20, 0x67, 0xa2, 0x9d, 0x56, + 0xf0, 0xa8, 0x67, 0x4d, 0xb4, 0xc3, 0x94, 0x82, 0x6c, 0x24, 0x06, 0xd9, 0x58, 0x5a, 0x08, 0xb9, + 0x7f, 0xda, 0x73, 0x3f, 0xb0, 0xab, 0x24, 0xd0, 0xab, 0x20, 0x30, 0xe3, 0xb9, 0x2d, 0x69, 0xf0, + 0x9f, 0x26, 0xd6, 0x56, 0xb6, 0x91, 0x62, 0x8f, 0x76, 0x70, 0x94, 0x0f, 0x52, 0xc8, 0x07, 0xde, + 0xf3, 0xa1, 0x6f, 0x57, 0x9a, 0x81, 0x33, 0x03, 0x13, 0xbe, 0x07, 0xbf, 0x73, 0x94, 0x57, 0xe6, + 0xdc, 0xe0, 0x49, 0xdd, 0xd4, 0xb5, 0x58, 0x7f, 0x02, 0x59, 0x30, 0x19, 0x9b, 0x05, 0xf7, 0x41, + 0x24, 0xac, 0xc6, 0x5c, 0xf3, 0x89, 0xb1, 0xae, 0x79, 0xc1, 0x44, 0x3b, 0xab, 0x91, 0x37, 0x7d, + 0x2d, 0x04, 0xbb, 0x3c, 0x48, 0xfd, 0x10, 0x16, 0xe9, 0x02, 0x48, 0xf1, 0xab, 0x3e, 0x21, 0xdf, + 0x70, 0x70, 0xd2, 0x17, 0x5b, 0x53, 0x6c, 0xc5, 0xc0, 0xfc, 0x2d, 0xc8, 0x29, 0x3d, 0x67, 0xcb, + 0xb2, 0x75, 0x67, 0x8f, 0x11, 0xd1, 0x10, 0x7e, 0xfc, 0xee, 0x46, 0xd1, 0x2d, 0x04, 0xcb, 0xac, + 0x62, 0xad, 0x3b, 0xb6, 0x6e, 0x6a, 0x72, 0x5f, 0x94, 0x7f, 0x03, 0xd2, 0x5d, 0x6a, 0x81, 0x92, + 0x94, 0xaf, 0x0b, 0xc3, 0x60, 0xd9, 0x0e, 0x8d, 0x1c, 0xa9, 0x1c, 0xac, 0x1a, 0xb8, 0x2a, 0xec, + 0x64, 0xf4, 0x8d, 0x11, 0x88, 0xc5, 0x41, 0x88, 0x4c, 0x57, 0x9a, 0xa5, 0xd7, 0x5a, 0x70, 0xca, + 0x07, 0xf3, 0x3d, 0x03, 0xb3, 0xde, 0x53, 0x2d, 0xff, 0xd0, 0x1f, 0x17, 0xcc, 0x3f, 0x52, 0x4c, + 0x47, 0xa2, 0x0a, 0xba, 0x29, 0xdd, 0xa0, 0xa8, 0x82, 0x53, 0x23, 0x0f, 0xfb, 0x17, 0x1c, 0xe4, + 0x9b, 0x58, 0x5b, 0xd3, 0x4d, 0x92, 0x84, 0xc7, 0x0f, 0xd9, 0xeb, 0x04, 0x25, 0x4d, 0x6c, 0x12, + 0xb4, 0x44, 0x25, 0xd9, 0x28, 0x1d, 0xec, 0x97, 0x33, 0x2c, 0xb3, 0xf1, 0x9f, 0xfb, 0xe5, 0x93, + 0x7b, 0x8a, 0xb1, 0xbd, 0x24, 0x79, 0x42, 0x92, 0x9c, 0x61, 0xd9, 0x8e, 0x59, 0x2d, 0x18, 0x84, + 0x36, 0xe5, 0x41, 0xf3, 0xfc, 0x92, 0xce, 0xc0, 0xe9, 0xc0, 0xd0, 0x0f, 0xd4, 0x57, 0x1c, 0xad, + 0x04, 0x77, 0xcd, 0xee, 0x2b, 0x04, 0x70, 0x71, 0x18, 0x80, 0x5f, 0x4b, 0xfa, 0x9e, 0xb9, 0xb5, + 0xa4, 0x3f, 0xe1, 0x83, 0xf8, 0x21, 0x49, 0x3b, 0x36, 0xda, 0x4d, 0x2f, 0x9b, 0x6a, 0x54, 0xef, + 0x7b, 0x5c, 0x54, 0xc3, 0xaf, 0x8c, 0xc4, 0x0b, 0xbe, 0x32, 0x92, 0x2f, 0xf0, 0xca, 0xe0, 0xcf, + 0x01, 0xf4, 0x08, 0x7e, 0xe6, 0x4a, 0x8a, 0xb6, 0x48, 0xb9, 0x9e, 0xc7, 0x48, 0xbf, 0x6b, 0x4c, + 0x07, 0xbb, 0x46, 0xbf, 0x21, 0xcc, 0x44, 0x34, 0x84, 0xd9, 0x23, 0xf4, 0x21, 0xb9, 0x97, 0xdb, + 0x10, 0x92, 0x9a, 0x6f, 0xf5, 0xec, 0x0e, 0x12, 0xc0, 0xad, 0xf9, 0x74, 0x44, 0x5a, 0xb5, 0x76, + 0x4f, 0xdf, 0x26, 0x97, 0x41, 0x9e, 0xb5, 0x6a, 0xee, 0x90, 0x5c, 0x9f, 0x34, 0x9d, 0xb6, 0x14, + 0xbc, 0x25, 0x14, 0xdc, 0x97, 0x90, 0xa5, 0xa2, 0xb7, 0x14, 0xbc, 0xb5, 0x74, 0x6b, 0x38, 0xab, + 0x16, 0x06, 0x1e, 0x65, 0xd1, 0xa9, 0x22, 0xdd, 0x83, 0x4b, 0xa3, 0x25, 0x8e, 0xd9, 0x43, 0x7e, + 0xcb, 0xc1, 0x29, 0x72, 0x04, 0xed, 0x9e, 0x89, 0x36, 0x14, 0x6c, 0xbc, 0xb2, 0xe3, 0x76, 0x65, + 0x98, 0x98, 0x69, 0xbf, 0x5e, 0x0c, 0x78, 0x27, 0xcd, 0xc1, 0xec, 0xd0, 0xa4, 0x07, 0xbf, 0xfe, + 0x79, 0x1e, 0x12, 0x4d, 0xac, 0xf1, 0xeb, 0x90, 0xeb, 0x3f, 0xd7, 0x23, 0x12, 0x3b, 0xf8, 0xd0, + 0x15, 0x2f, 0x8d, 0x5e, 0xf7, 0xb9, 0x7d, 0x1f, 0x4e, 0x47, 0x9d, 0xe3, 0x4a, 0xa4, 0x7a, 0x84, + 0xa4, 0x78, 0x73, 0x5c, 0x49, 0x7f, 0x4b, 0x07, 0x8a, 0x91, 0x6f, 0xb4, 0x2b, 0xe3, 0x5a, 0xaa, + 0x8b, 0x8b, 0x63, 0x8b, 0xfa, 0xbb, 0x22, 0x38, 0x19, 0x7e, 0x56, 0x5c, 0x88, 0xb4, 0x12, 0x92, + 0x12, 0xaf, 0x8f, 0x23, 0x15, 0xdc, 0x26, 0xdc, 0x85, 0x47, 0x6f, 0x13, 0x92, 0x8a, 0xd9, 0x26, + 0xae, 0x1f, 0x7e, 0x17, 0xf2, 0xc1, 0xbe, 0x77, 0x3e, 0x52, 0x39, 0x20, 0x21, 0x56, 0x0e, 0x93, + 0xf0, 0x4d, 0xdf, 0x03, 0x08, 0x34, 0xac, 0xe5, 0x48, 0xbd, 0xbe, 0x80, 0x78, 0xf9, 0x10, 0x01, + 0xdf, 0xee, 0x07, 0x30, 0x13, 0xd7, 0x85, 0x5e, 0x1f, 0xe1, 0xdc, 0x90, 0xb4, 0xf8, 0xbf, 0xa3, + 0x48, 0xfb, 0xdb, 0xdf, 0x87, 0xc2, 0x40, 0xcf, 0x77, 0x7e, 0x84, 0x15, 0x26, 0x22, 0x5e, 0x39, + 0x54, 0x24, 0x68, 0x7d, 0xa0, 0x09, 0x8b, 0xb6, 0x1e, 0x14, 0x89, 0xb1, 0x1e, 0xd9, 0x10, 0xad, + 0x41, 0xd6, 0x6f, 0x7c, 0xce, 0x45, 0xaa, 0x79, 0xcb, 0xe2, 0xc5, 0x91, 0xcb, 0xc1, 0x20, 0x07, + 0x7a, 0x91, 0xe8, 0x20, 0xf7, 0x05, 0x62, 0x82, 0x3c, 0xdc, 0x22, 0xf0, 0x9f, 0x70, 0x30, 0x37, + 0xaa, 0x3f, 0xb8, 0x19, 0x5f, 0x96, 0xa2, 0x35, 0xc4, 0xd7, 0x8e, 0xaa, 0xe1, 0xfb, 0xd2, 0x86, + 0x13, 0xa1, 0x4b, 0x60, 0x21, 0x9a, 0x9c, 0x01, 0x21, 0xf1, 0xda, 0x18, 0x42, 0xde, 0x1e, 0x8d, + 0xdb, 0x4f, 0x7e, 0x2d, 0x4d, 0x3c, 0x39, 0x28, 0x71, 0x4f, 0x0f, 0x4a, 0xdc, 0x2f, 0x07, 0x25, + 0xee, 0xb3, 0x67, 0xa5, 0x89, 0xa7, 0xcf, 0x4a, 0x13, 0x3f, 0x3d, 0x2b, 0x4d, 0xbc, 0x77, 0x29, + 0x70, 0x3f, 0xaf, 0x58, 0xd8, 0xd8, 0xf0, 0x7e, 0xbb, 0x55, 0x6b, 0xbb, 0xec, 0x37, 0x5c, 0x7a, + 0x47, 0xb7, 0xd3, 0xf4, 0x37, 0xd9, 0xff, 0xfe, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x47, 0x63, 0xda, + 0xd1, 0x5d, 0x16, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1472,6 +1565,9 @@ type MsgClient interface { // // Since: 0.40 StoreAndInstantiateContract(ctx context.Context, in *MsgStoreAndInstantiateContract, opts ...grpc.CallOption) (*MsgStoreAndInstantiateContractResponse, error) + // PruneWasmCodes defines a governance operation for pruning a set of + // code ids in the system. The authority is defined in the keeper. + PruneWasmCodes(ctx context.Context, in *MsgPruneWasmCodes, opts ...grpc.CallOption) (*MsgPruneWasmCodesResponse, error) } type msgClient struct { @@ -1599,6 +1695,15 @@ func (c *msgClient) StoreAndInstantiateContract(ctx context.Context, in *MsgStor return out, nil } +func (c *msgClient) PruneWasmCodes(ctx context.Context, in *MsgPruneWasmCodes, opts ...grpc.CallOption) (*MsgPruneWasmCodesResponse, error) { + out := new(MsgPruneWasmCodesResponse) + err := c.cc.Invoke(ctx, "/cosmwasm.wasm.v1.Msg/PruneWasmCodes", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { // StoreCode to submit Wasm code to the system @@ -1644,6 +1749,9 @@ type MsgServer interface { // // Since: 0.40 StoreAndInstantiateContract(context.Context, *MsgStoreAndInstantiateContract) (*MsgStoreAndInstantiateContractResponse, error) + // PruneWasmCodes defines a governance operation for pruning a set of + // code ids in the system. The authority is defined in the keeper. + PruneWasmCodes(context.Context, *MsgPruneWasmCodes) (*MsgPruneWasmCodesResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -1701,6 +1809,10 @@ func (*UnimplementedMsgServer) StoreAndInstantiateContract(ctx context.Context, return nil, status.Errorf(codes.Unimplemented, "method StoreAndInstantiateContract not implemented") } +func (*UnimplementedMsgServer) PruneWasmCodes(ctx context.Context, req *MsgPruneWasmCodes) (*MsgPruneWasmCodesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PruneWasmCodes not implemented") +} + func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) } @@ -1939,6 +2051,24 @@ func _Msg_StoreAndInstantiateContract_Handler(srv interface{}, ctx context.Conte return interceptor(ctx, in, info, handler) } +func _Msg_PruneWasmCodes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgPruneWasmCodes) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).PruneWasmCodes(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmwasm.wasm.v1.Msg/PruneWasmCodes", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).PruneWasmCodes(ctx, req.(*MsgPruneWasmCodes)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "cosmwasm.wasm.v1.Msg", HandlerType: (*MsgServer)(nil), @@ -1995,6 +2125,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "StoreAndInstantiateContract", Handler: _Msg_StoreAndInstantiateContract_Handler, }, + { + MethodName: "PruneWasmCodes", + Handler: _Msg_PruneWasmCodes_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "cosmwasm/wasm/v1/tx.proto", @@ -3110,6 +3244,77 @@ func (m *MsgStoreAndInstantiateContractResponse) MarshalToSizedBuffer(dAtA []byt return len(dAtA) - i, nil } +func (m *MsgPruneWasmCodes) 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 *MsgPruneWasmCodes) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgPruneWasmCodes) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.CodeIDs) > 0 { + dAtA10 := make([]byte, len(m.CodeIDs)*10) + var j9 int + for _, num := range m.CodeIDs { + for num >= 1<<7 { + dAtA10[j9] = uint8(uint64(num)&0x7f | 0x80) + num >>= 7 + j9++ + } + dAtA10[j9] = uint8(num) + j9++ + } + i -= j9 + copy(dAtA[i:], dAtA10[:j9]) + i = encodeVarintTx(dAtA, i, uint64(j9)) + i-- + dAtA[i] = 0x12 + } + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgPruneWasmCodesResponse) 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 *MsgPruneWasmCodesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgPruneWasmCodesResponse) 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 @@ -3617,6 +3822,35 @@ func (m *MsgStoreAndInstantiateContractResponse) Size() (n int) { return n } +func (m *MsgPruneWasmCodes) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if len(m.CodeIDs) > 0 { + l = 0 + for _, e := range m.CodeIDs { + l += sovTx(uint64(e)) + } + n += 1 + sovTx(uint64(l)) + l + } + return n +} + +func (m *MsgPruneWasmCodesResponse) 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 } @@ -7053,6 +7287,216 @@ func (m *MsgStoreAndInstantiateContractResponse) Unmarshal(dAtA []byte) error { return nil } +func (m *MsgPruneWasmCodes) 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: MsgPruneWasmCodes: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgPruneWasmCodes: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authority", 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.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType == 0 { + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.CodeIDs = append(m.CodeIDs, v) + } else if wireType == 2 { + var packedLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + packedLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + packedLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + 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.CodeIDs) == 0 { + m.CodeIDs = make([]uint64, 0, elementCount) + } + for iNdEx < postIndex { + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.CodeIDs = append(m.CodeIDs, v) + } + } else { + return fmt.Errorf("proto: wrong wireType = %d for field CodeIDs", wireType) + } + 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 *MsgPruneWasmCodesResponse) 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: MsgPruneWasmCodesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgPruneWasmCodesResponse: 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 diff --git a/x/wasm/types/tx_test.go b/x/wasm/types/tx_test.go index fd5cf5ba11..4edf6e4292 100644 --- a/x/wasm/types/tx_test.go +++ b/x/wasm/types/tx_test.go @@ -834,9 +834,7 @@ func TestMsgPinCodesValidation(t *testing.T) { } func TestMsgUnpinCodesValidation(t *testing.T) { - bad, err := sdk.AccAddressFromHexUnsafe("012345") - require.NoError(t, err) - badAddress := bad.String() + badAddress := "012345" // proper address size goodAddress := sdk.AccAddress(make([]byte, 20)).String() @@ -1129,3 +1127,50 @@ func TestMsgStoreAndInstantiateContractValidation(t *testing.T) { }) } } + +func TestMsgPruneWasmCodesValidation(t *testing.T) { + badAddress := "012345" + // proper address size + goodAddress := sdk.AccAddress(make([]byte, 20)).String() + + specs := map[string]struct { + src MsgPruneWasmCodes + expErr bool + }{ + "all good": { + src: MsgPruneWasmCodes{ + Authority: goodAddress, + CodeIDs: []uint64{1}, + }, + }, + "bad authority": { + src: MsgPruneWasmCodes{ + Authority: badAddress, + CodeIDs: []uint64{1}, + }, + expErr: true, + }, + "empty authority": { + src: MsgPruneWasmCodes{ + CodeIDs: []uint64{1}, + }, + expErr: true, + }, + "empty code ids": { + src: MsgPruneWasmCodes{ + Authority: goodAddress, + }, + expErr: true, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + err := spec.src.ValidateBasic() + if spec.expErr { + require.Error(t, err) + return + } + require.NoError(t, err) + }) + } +} From 821f63266403a7a307f1eae5ba69f3a98eba5911 Mon Sep 17 00:00:00 2001 From: Pino' Surace Date: Fri, 16 Jun 2023 15:26:39 +0200 Subject: [PATCH 02/18] Fix test --- x/wasm/keeper/keeper.go | 2 +- x/wasm/keeper/msg_server_integration_test.go | 39 ++++++++++++-------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index ae20ccd594..0ab9dc9014 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -1223,7 +1223,7 @@ func (h DefaultWasmVMContractResponseHandler) Handle(ctx sdk.Context, contractAd func (k Keeper) PruneWasmCodes(ctx sdk.Context, codeIDs []uint64) error { for _, c := range codeIDs { if k.IsPinnedCode(ctx, c) { - return errorsmod.Wrap(types.ErrInvalid, fmt.Sprintf("code %d is pinned", c)) + continue } k.deleteCodeInfo(ctx, c) } diff --git a/x/wasm/keeper/msg_server_integration_test.go b/x/wasm/keeper/msg_server_integration_test.go index 2e3cec2e69..973c62ce06 100644 --- a/x/wasm/keeper/msg_server_integration_test.go +++ b/x/wasm/keeper/msg_server_integration_test.go @@ -864,29 +864,32 @@ func TestPruneWasmCodes(t *testing.T) { ) specs := map[string]struct { - addr string - pinCode bool - expErr bool + addr string + pinCode bool + expPruned bool + expErr bool }{ "authority can prune unpinned code": { - addr: authority, - pinCode: false, - expErr: false, + addr: authority, + pinCode: false, + expPruned: true, }, "authority cannot prune pinned code": { - addr: authority, - pinCode: true, - expErr: true, + addr: authority, + pinCode: true, + expPruned: false, }, "other address cannot prune unpinned code": { - addr: myAddress.String(), - pinCode: false, - expErr: true, + addr: myAddress.String(), + pinCode: false, + expPruned: false, + expErr: true, }, "other address cannot prune pinned code": { - addr: myAddress.String(), - pinCode: true, - expErr: true, + addr: myAddress.String(), + pinCode: true, + expPruned: false, + expErr: true, }, } for name, spec := range specs { @@ -925,10 +928,14 @@ func TestPruneWasmCodes(t *testing.T) { // then if spec.expErr { require.Error(t, err) - assert.NotNil(t, wasmApp.WasmKeeper.GetCodeInfo(ctx, result.CodeID)) } else { require.NoError(t, err) + } + + if spec.expPruned { assert.Nil(t, wasmApp.WasmKeeper.GetCodeInfo(ctx, result.CodeID)) + } else { + assert.NotNil(t, wasmApp.WasmKeeper.GetCodeInfo(ctx, result.CodeID)) } }) } From 6129f8bc8262c39b759a933f15b94fb3071fd94d Mon Sep 17 00:00:00 2001 From: Pino' Surace Date: Fri, 16 Jun 2023 15:42:17 +0200 Subject: [PATCH 03/18] Fix docs --- docs/proto/proto-docs.md | 2 +- proto/cosmwasm/wasm/v1/tx.proto | 2 +- x/wasm/client/cli/gov_tx.go | 2 +- x/wasm/keeper/msg_server.go | 2 +- x/wasm/types/tx.pb.go | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/proto/proto-docs.md b/docs/proto/proto-docs.md index 8b760b8b99..05df451f54 100644 --- a/docs/proto/proto-docs.md +++ b/docs/proto/proto-docs.md @@ -1832,7 +1832,7 @@ Since: 0.40 | | | `StoreAndInstantiateContract` | [MsgStoreAndInstantiateContract](#cosmwasm.wasm.v1.MsgStoreAndInstantiateContract) | [MsgStoreAndInstantiateContractResponse](#cosmwasm.wasm.v1.MsgStoreAndInstantiateContractResponse) | StoreAndInstantiateContract defines a governance operation for storing and instantiating the contract. The authority is defined in the keeper. Since: 0.40 | | -| `PruneWasmCodes` | [MsgPruneWasmCodes](#cosmwasm.wasm.v1.MsgPruneWasmCodes) | [MsgPruneWasmCodesResponse](#cosmwasm.wasm.v1.MsgPruneWasmCodesResponse) | PruneWasmCodes defines a governance operation for pruning a set of code ids in the system. The authority is defined in the keeper. | | +| `PruneWasmCodes` | [MsgPruneWasmCodes](#cosmwasm.wasm.v1.MsgPruneWasmCodes) | [MsgPruneWasmCodesResponse](#cosmwasm.wasm.v1.MsgPruneWasmCodesResponse) | PruneWasmCodes defines a governance operation for pruning a set of unpinned code ids in the system. The authority is defined in the keeper. | | diff --git a/proto/cosmwasm/wasm/v1/tx.proto b/proto/cosmwasm/wasm/v1/tx.proto index 4e89e78295..02d9d50e89 100644 --- a/proto/cosmwasm/wasm/v1/tx.proto +++ b/proto/cosmwasm/wasm/v1/tx.proto @@ -61,7 +61,7 @@ service Msg { rpc StoreAndInstantiateContract(MsgStoreAndInstantiateContract) returns (MsgStoreAndInstantiateContractResponse); // PruneWasmCodes defines a governance operation for pruning a set of - // code ids in the system. The authority is defined in the keeper. + // unpinned code ids in the system. The authority is defined in the keeper. rpc PruneWasmCodes(MsgPruneWasmCodes) returns (MsgPruneWasmCodesResponse); } diff --git a/x/wasm/client/cli/gov_tx.go b/x/wasm/client/cli/gov_tx.go index a714c42314..68375992d3 100644 --- a/x/wasm/client/cli/gov_tx.go +++ b/x/wasm/client/cli/gov_tx.go @@ -805,7 +805,7 @@ $ %s tx gov submit-proposal update-instantiate-config 1:nobody 2:everybody 3:%s1 func ProposalPruneWasmCodesCmd() *cobra.Command { cmd := &cobra.Command{ Use: "prune-wasm-codes [code-ids] --title [text] --summary [text] --authority [address]", - Short: "Submit a prune wasm codes proposal for pruning codes in the system", + Short: "Submit a prune wasm codes proposal for pruning unpinned codes in the system", Args: cobra.MinimumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { clientCtx, proposalTitle, summary, deposit, err := getProposalInfo(cmd) diff --git a/x/wasm/keeper/msg_server.go b/x/wasm/keeper/msg_server.go index ebe4666280..21ecdf8dd4 100644 --- a/x/wasm/keeper/msg_server.go +++ b/x/wasm/keeper/msg_server.go @@ -364,7 +364,7 @@ func (m msgServer) selectAuthorizationPolicy(actor string) AuthorizationPolicy { return DefaultAuthorizationPolicy{} } -// PruneWasmCodes prunes a set of codeIDs in the system. +// PruneWasmCodes prunes a set of unpinned code ids in the system. func (m msgServer) PruneWasmCodes(goCtx context.Context, req *types.MsgPruneWasmCodes) (*types.MsgPruneWasmCodesResponse, error) { if err := req.ValidateBasic(); err != nil { return nil, err diff --git a/x/wasm/types/tx.pb.go b/x/wasm/types/tx.pb.go index 41df23f309..bce2218454 100644 --- a/x/wasm/types/tx.pb.go +++ b/x/wasm/types/tx.pb.go @@ -1566,7 +1566,7 @@ type MsgClient interface { // Since: 0.40 StoreAndInstantiateContract(ctx context.Context, in *MsgStoreAndInstantiateContract, opts ...grpc.CallOption) (*MsgStoreAndInstantiateContractResponse, error) // PruneWasmCodes defines a governance operation for pruning a set of - // code ids in the system. The authority is defined in the keeper. + // unpinned code ids in the system. The authority is defined in the keeper. PruneWasmCodes(ctx context.Context, in *MsgPruneWasmCodes, opts ...grpc.CallOption) (*MsgPruneWasmCodesResponse, error) } @@ -1750,7 +1750,7 @@ type MsgServer interface { // Since: 0.40 StoreAndInstantiateContract(context.Context, *MsgStoreAndInstantiateContract) (*MsgStoreAndInstantiateContractResponse, error) // PruneWasmCodes defines a governance operation for pruning a set of - // code ids in the system. The authority is defined in the keeper. + // unpinned code ids in the system. The authority is defined in the keeper. PruneWasmCodes(context.Context, *MsgPruneWasmCodes) (*MsgPruneWasmCodesResponse, error) } From 2cbb4fb903bddededc526cd79cde12f323c0e40f Mon Sep 17 00:00:00 2001 From: Pino' Surace Date: Fri, 16 Jun 2023 16:25:10 +0200 Subject: [PATCH 04/18] Add remove code method to wasmvm engine --- x/wasm/keeper/keeper.go | 6 ++++++ x/wasm/keeper/wasmtesting/mock_engine.go | 8 ++++++++ x/wasm/types/wasmer_engine.go | 3 +++ 3 files changed, 17 insertions(+) diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index 0ab9dc9014..9240fbdd1b 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -1225,6 +1225,12 @@ func (k Keeper) PruneWasmCodes(ctx sdk.Context, codeIDs []uint64) error { if k.IsPinnedCode(ctx, c) { continue } + + info := k.GetCodeInfo(ctx, c) + if info == nil { + return types.ErrNoSuchCodeFn(c).Wrapf("code id %d", c) + } + k.wasmVM.RemoveCode(info.CodeHash) k.deleteCodeInfo(ctx, c) } return nil diff --git a/x/wasm/keeper/wasmtesting/mock_engine.go b/x/wasm/keeper/wasmtesting/mock_engine.go index 383da90b7f..da13616ec7 100644 --- a/x/wasm/keeper/wasmtesting/mock_engine.go +++ b/x/wasm/keeper/wasmtesting/mock_engine.go @@ -36,6 +36,7 @@ type MockWasmer struct { IBCPacketTimeoutFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketTimeoutMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) PinFn func(checksum wasmvm.Checksum) error UnpinFn func(checksum wasmvm.Checksum) error + RemoveCodeFn func(checksum wasmvm.Checksum) error GetMetricsFn func() (*wasmvmtypes.Metrics, error) } @@ -165,6 +166,13 @@ func (m *MockWasmer) Unpin(checksum wasmvm.Checksum) error { return m.UnpinFn(checksum) } +func (m *MockWasmer) RemoveCode(checksum wasmvm.Checksum) error { + if m.UnpinFn == nil { + panic("not supposed to be called!") + } + return m.RemoveCodeFn(checksum) +} + func (m *MockWasmer) GetMetrics() (*wasmvmtypes.Metrics, error) { if m.GetMetricsFn == nil { panic("not expected to be called") diff --git a/x/wasm/types/wasmer_engine.go b/x/wasm/types/wasmer_engine.go index 9b2efdef50..16f5c9916f 100644 --- a/x/wasm/types/wasmer_engine.go +++ b/x/wasm/types/wasmer_engine.go @@ -237,6 +237,9 @@ type WasmerEngine interface { // Unpin is idempotent. Unpin(checksum wasmvm.Checksum) error + // RemoveCode removes the wasm code referenced by checksum. + RemoveCode(checksum wasmvm.Checksum) error + // GetMetrics some internal metrics for monitoring purposes. GetMetrics() (*wasmvmtypes.Metrics, error) } From 39c5442aab04d31be800cfa2a7d77a448db9163c Mon Sep 17 00:00:00 2001 From: Pino' Surace Date: Mon, 19 Jun 2023 17:41:01 +0200 Subject: [PATCH 05/18] Fix comments --- docs/proto/proto-docs.md | 2 +- proto/cosmwasm/wasm/v1/tx.proto | 8 +- x/wasm/client/cli/gov_tx.go | 14 +- x/wasm/keeper/keeper.go | 33 +- x/wasm/keeper/msg_server.go | 4 +- x/wasm/keeper/msg_server_integration_test.go | 4 +- x/wasm/types/tx.go | 4 +- x/wasm/types/tx.pb.go | 306 +++++++------------ x/wasm/types/tx_test.go | 12 +- 9 files changed, 166 insertions(+), 221 deletions(-) diff --git a/docs/proto/proto-docs.md b/docs/proto/proto-docs.md index 05df451f54..bf287b7bb6 100644 --- a/docs/proto/proto-docs.md +++ b/docs/proto/proto-docs.md @@ -1543,7 +1543,7 @@ MsgPruneWasmCodes is the MsgPruneWasmCodes request type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | `authority` | [string](#string) | | Authority is the address of the governance account. | -| `code_ids` | [uint64](#uint64) | repeated | CodeIDs references the WASM codes | +| `latest_code_id` | [uint64](#uint64) | | LatestCodeID references the greater limit until unpinned code ids will be pruned | diff --git a/proto/cosmwasm/wasm/v1/tx.proto b/proto/cosmwasm/wasm/v1/tx.proto index 02d9d50e89..5313dc93d6 100644 --- a/proto/cosmwasm/wasm/v1/tx.proto +++ b/proto/cosmwasm/wasm/v1/tx.proto @@ -400,11 +400,9 @@ message MsgPruneWasmCodes { // Authority is the address of the governance account. string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; - // CodeIDs references the WASM codes - repeated uint64 code_ids = 2 [ - (gogoproto.customname) = "CodeIDs", - (gogoproto.moretags) = "yaml:\"code_ids\"" - ]; + // LatestCodeID references the upper limit until unpinned + // code ids will be pruned + uint64 latest_code_id = 2 [ (gogoproto.customname) = "LatestCodeID" ]; } // MsgPruneWasmCodesResponse defines the response structure for executing a diff --git a/x/wasm/client/cli/gov_tx.go b/x/wasm/client/cli/gov_tx.go index 68375992d3..fa11ad938c 100644 --- a/x/wasm/client/cli/gov_tx.go +++ b/x/wasm/client/cli/gov_tx.go @@ -804,9 +804,9 @@ $ %s tx gov submit-proposal update-instantiate-config 1:nobody 2:everybody 3:%s1 func ProposalPruneWasmCodesCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "prune-wasm-codes [code-ids] --title [text] --summary [text] --authority [address]", - Short: "Submit a prune wasm codes proposal for pruning unpinned codes in the system", - Args: cobra.MinimumNArgs(1), + Use: "prune-wasm-codes [latest-code-id] --title [text] --summary [text] --authority [address]", + Short: "Submit a prune wasm codes proposal for pruning unpinned wasm codes smaller than latest-code-id", + Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { clientCtx, proposalTitle, summary, deposit, err := getProposalInfo(cmd) if err != nil { @@ -821,14 +821,14 @@ func ProposalPruneWasmCodesCmd() *cobra.Command { return errors.New("authority address is required") } - codeIds, err := parsePinCodesArgs(args) + codeID, err := strconv.ParseUint(args[1], 10, 64) if err != nil { - return err + return fmt.Errorf("invalid code ID: %s", err) } msg := types.MsgPruneWasmCodes{ - Authority: authority, - CodeIDs: codeIds, + Authority: authority, + LatestCodeID: codeID, } proposalMsg, err := v1.NewMsgSubmitProposal([]sdk.Msg{&msg}, deposit, clientCtx.GetFromAddress().String(), "", proposalTitle, summary) diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index 9240fbdd1b..1cdef26809 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -1219,19 +1219,38 @@ func (h DefaultWasmVMContractResponseHandler) Handle(ctx sdk.Context, contractAd return result, nil } -// PruneWasmCodes deletes code info for unpinned codes. -func (k Keeper) PruneWasmCodes(ctx sdk.Context, codeIDs []uint64) error { - for _, c := range codeIDs { +// PruneWasmCodes deletes code info for unpinned codes smaller than given code id. +func (k Keeper) PruneWasmCodes(ctx sdk.Context, codeID uint64) error { + pinnedCodesHash := make(map[string]struct{}, 0) + unpinnedCodes := make([]uint64, 0) + + for c := uint64(1); c < codeID; c++ { + info := k.GetCodeInfo(ctx, c) + if info == nil { + continue + } + if k.IsPinnedCode(ctx, c) { + pinnedCodesHash[string(info.CodeHash)] = struct{}{} continue } + unpinnedCodes = append(unpinnedCodes, c) + } - info := k.GetCodeInfo(ctx, c) + for _, code := range unpinnedCodes { + info := k.GetCodeInfo(ctx, code) if info == nil { - return types.ErrNoSuchCodeFn(c).Wrapf("code id %d", c) + continue + } + + if _, found := pinnedCodesHash[string(info.CodeHash)]; found { + continue + } + + if err := k.wasmVM.RemoveCode(info.CodeHash); err != nil { + continue } - k.wasmVM.RemoveCode(info.CodeHash) - k.deleteCodeInfo(ctx, c) + k.deleteCodeInfo(ctx, code) } return nil } diff --git a/x/wasm/keeper/msg_server.go b/x/wasm/keeper/msg_server.go index 21ecdf8dd4..a586df8986 100644 --- a/x/wasm/keeper/msg_server.go +++ b/x/wasm/keeper/msg_server.go @@ -364,7 +364,7 @@ func (m msgServer) selectAuthorizationPolicy(actor string) AuthorizationPolicy { return DefaultAuthorizationPolicy{} } -// PruneWasmCodes prunes a set of unpinned code ids in the system. +// PruneWasmCodes prunes unpinned code ids smaller than given code id. func (m msgServer) PruneWasmCodes(goCtx context.Context, req *types.MsgPruneWasmCodes) (*types.MsgPruneWasmCodesResponse, error) { if err := req.ValidateBasic(); err != nil { return nil, err @@ -375,7 +375,7 @@ func (m msgServer) PruneWasmCodes(goCtx context.Context, req *types.MsgPruneWasm } ctx := sdk.UnwrapSDKContext(goCtx) - err := m.keeper.PruneWasmCodes(ctx, req.CodeIDs) + err := m.keeper.PruneWasmCodes(ctx, req.LatestCodeID) if err != nil { return nil, err } diff --git a/x/wasm/keeper/msg_server_integration_test.go b/x/wasm/keeper/msg_server_integration_test.go index 973c62ce06..16c25d3797 100644 --- a/x/wasm/keeper/msg_server_integration_test.go +++ b/x/wasm/keeper/msg_server_integration_test.go @@ -920,8 +920,8 @@ func TestPruneWasmCodes(t *testing.T) { // when msgPruneCodes := &types.MsgPruneWasmCodes{ - Authority: spec.addr, - CodeIDs: []uint64{result.CodeID}, + Authority: spec.addr, + LatestCodeID: result.CodeID, } _, err = wasmApp.MsgServiceRouter().Handler(msgPruneCodes)(ctx, msgPruneCodes) diff --git a/x/wasm/types/tx.go b/x/wasm/types/tx.go index 90f636ae8b..9f1a9e1a86 100644 --- a/x/wasm/types/tx.go +++ b/x/wasm/types/tx.go @@ -640,8 +640,8 @@ func (msg MsgPruneWasmCodes) ValidateBasic() error { if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil { return errorsmod.Wrap(err, "authority") } - if len(msg.CodeIDs) == 0 { - return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "empty code ids") + if msg.LatestCodeID == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "latest code id is required") } return nil } diff --git a/x/wasm/types/tx.pb.go b/x/wasm/types/tx.pb.go index bce2218454..708a180d86 100644 --- a/x/wasm/types/tx.pb.go +++ b/x/wasm/types/tx.pb.go @@ -1293,8 +1293,9 @@ var xxx_messageInfo_MsgStoreAndInstantiateContractResponse proto.InternalMessage type MsgPruneWasmCodes struct { // Authority is the address of the governance account. Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` - // CodeIDs references the WASM codes - CodeIDs []uint64 `protobuf:"varint,2,rep,packed,name=code_ids,json=codeIds,proto3" json:"code_ids,omitempty" yaml:"code_ids"` + // LatestCodeID references the greater limit until unpinned + // code ids will be pruned + LatestCodeID uint64 `protobuf:"varint,2,opt,name=latest_code_id,json=latestCodeId,proto3" json:"latest_code_id,omitempty"` } func (m *MsgPruneWasmCodes) Reset() { *m = MsgPruneWasmCodes{} } @@ -1411,101 +1412,102 @@ func init() { func init() { proto.RegisterFile("cosmwasm/wasm/v1/tx.proto", fileDescriptor_4f74d82755520264) } var fileDescriptor_4f74d82755520264 = []byte{ - // 1493 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x58, 0xcd, 0x6f, 0xdb, 0xc6, - 0x12, 0x37, 0xad, 0xef, 0x91, 0x5e, 0xe2, 0x30, 0x8a, 0x4d, 0xd3, 0x89, 0xe4, 0xd0, 0xf9, 0x50, - 0xbe, 0xa4, 0x58, 0xef, 0xbd, 0xa0, 0x75, 0x4f, 0x96, 0x53, 0xa0, 0x0e, 0xa0, 0xd6, 0xa0, 0x91, - 0x18, 0x2d, 0x02, 0x08, 0x94, 0xb8, 0xa6, 0x89, 0x98, 0xa4, 0xca, 0xa5, 0x62, 0xfb, 0xd0, 0x4b, - 0x0b, 0x14, 0x68, 0x4f, 0xbd, 0xf6, 0x0f, 0x28, 0xd0, 0xf6, 0xd2, 0x14, 0xe8, 0xa1, 0xc7, 0x1c, - 0x03, 0xf4, 0x12, 0xf4, 0xd4, 0x93, 0xdb, 0x3a, 0x05, 0xd2, 0x5b, 0x81, 0x1e, 0x7b, 0x2a, 0x76, - 0x97, 0xa4, 0x28, 0x8a, 0x94, 0x65, 0xa7, 0x41, 0x0e, 0xbd, 0xd8, 0xdc, 0xdd, 0x99, 0xd9, 0xf9, - 0xfd, 0x66, 0x76, 0x76, 0x56, 0x30, 0xdb, 0xb1, 0xb0, 0xb1, 0xa3, 0x60, 0xa3, 0x46, 0xff, 0x3c, - 0x5c, 0xac, 0x39, 0xbb, 0xd5, 0xae, 0x6d, 0x39, 0x16, 0x3f, 0xe5, 0x2d, 0x55, 0xe9, 0x9f, 0x87, - 0x8b, 0x62, 0x89, 0xcc, 0x58, 0xb8, 0xd6, 0x56, 0x30, 0xaa, 0x3d, 0x5c, 0x6c, 0x23, 0x47, 0x59, - 0xac, 0x75, 0x2c, 0xdd, 0x64, 0x1a, 0xe2, 0x8c, 0xbb, 0x6e, 0x60, 0x8d, 0x58, 0x32, 0xb0, 0xe6, - 0x2e, 0x14, 0x35, 0x4b, 0xb3, 0xe8, 0x67, 0x8d, 0x7c, 0xb9, 0xb3, 0x67, 0x87, 0xf7, 0xde, 0xeb, - 0x22, 0xec, 0xae, 0xce, 0x32, 0x63, 0x2d, 0xa6, 0xc6, 0x06, 0xee, 0xd2, 0x29, 0xc5, 0xd0, 0x4d, - 0xab, 0x46, 0xff, 0xb2, 0x29, 0xe9, 0x37, 0x0e, 0x0a, 0x4d, 0xac, 0xad, 0x3b, 0x96, 0x8d, 0x56, - 0x2c, 0x15, 0xf1, 0xd3, 0x90, 0xc6, 0xc8, 0x54, 0x91, 0x2d, 0x70, 0xf3, 0x5c, 0x25, 0x27, 0xbb, - 0x23, 0xfe, 0x16, 0x9c, 0x20, 0xbb, 0xb5, 0xda, 0x7b, 0x0e, 0x6a, 0x75, 0x2c, 0x15, 0x09, 0x93, - 0xf3, 0x5c, 0xa5, 0xd0, 0x98, 0x3a, 0xd8, 0x2f, 0x17, 0x36, 0x96, 0xd7, 0x9b, 0x8d, 0x3d, 0x87, - 0x5a, 0x90, 0x0b, 0x44, 0xce, 0x1b, 0xf1, 0x77, 0x61, 0x5a, 0x37, 0xb1, 0xa3, 0x98, 0x8e, 0xae, - 0x38, 0xa8, 0xd5, 0x45, 0xb6, 0xa1, 0x63, 0xac, 0x5b, 0xa6, 0x90, 0x9a, 0xe7, 0x2a, 0xf9, 0x7a, - 0xa9, 0x1a, 0xa6, 0xab, 0xba, 0xdc, 0xe9, 0x20, 0x8c, 0x57, 0x2c, 0x73, 0x53, 0xd7, 0xe4, 0x33, - 0x01, 0xed, 0x35, 0x5f, 0x79, 0xe9, 0xfc, 0x87, 0xcf, 0x1f, 0x5d, 0x75, 0x7d, 0xfb, 0xf4, 0xf9, - 0xa3, 0xab, 0xa7, 0x28, 0x15, 0x41, 0x24, 0x77, 0x92, 0xd9, 0xc4, 0x54, 0xf2, 0x4e, 0x32, 0x9b, - 0x9c, 0x4a, 0x49, 0x1b, 0x50, 0x0c, 0xae, 0xc9, 0x08, 0x77, 0x2d, 0x13, 0x23, 0x7e, 0x01, 0x32, - 0x04, 0x4b, 0x4b, 0x57, 0x29, 0xdc, 0x64, 0x03, 0x0e, 0xf6, 0xcb, 0x69, 0x22, 0xb2, 0x7a, 0x5b, - 0x4e, 0x93, 0xa5, 0x55, 0x95, 0x17, 0x21, 0xdb, 0xd9, 0x42, 0x9d, 0x07, 0xb8, 0x67, 0x30, 0xd0, - 0xb2, 0x3f, 0x96, 0x1e, 0x4f, 0xc2, 0x74, 0x13, 0x6b, 0xab, 0x7d, 0x27, 0x57, 0x2c, 0xd3, 0xb1, - 0x95, 0x8e, 0x13, 0xcb, 0x64, 0x11, 0x52, 0x8a, 0x6a, 0xe8, 0x26, 0xb5, 0x95, 0x93, 0xd9, 0x20, - 0xe8, 0x49, 0x22, 0xd6, 0x93, 0x22, 0xa4, 0xb6, 0x95, 0x36, 0xda, 0x16, 0x92, 0x4c, 0x95, 0x0e, - 0xf8, 0x0a, 0x24, 0x0c, 0xac, 0x51, 0x3e, 0x0b, 0x8d, 0xe9, 0xbf, 0xf6, 0xcb, 0xbc, 0xac, 0xec, - 0x78, 0x6e, 0x34, 0x11, 0xc6, 0x8a, 0x86, 0x64, 0x22, 0xc2, 0x6f, 0x42, 0x6a, 0xb3, 0x67, 0xaa, - 0x58, 0x48, 0xcf, 0x27, 0x2a, 0xf9, 0xfa, 0x6c, 0xd5, 0x4d, 0x0f, 0x92, 0x98, 0x55, 0x37, 0x31, - 0xab, 0x2b, 0x96, 0x6e, 0x36, 0xfe, 0xff, 0x64, 0xbf, 0x3c, 0xf1, 0xf5, 0xcf, 0xe5, 0x8a, 0xa6, - 0x3b, 0x5b, 0xbd, 0x76, 0xb5, 0x63, 0x19, 0x6e, 0x2e, 0xb9, 0xff, 0x6e, 0x60, 0xf5, 0x81, 0x9b, - 0x77, 0x44, 0x01, 0x7f, 0xf9, 0xfc, 0xd1, 0x55, 0x4e, 0x66, 0xe6, 0x97, 0xae, 0x85, 0xa2, 0x33, - 0xe7, 0x45, 0x27, 0x82, 0x27, 0xe9, 0x6d, 0x28, 0x45, 0xaf, 0xf8, 0x51, 0x12, 0x20, 0xa3, 0xa8, - 0xaa, 0x8d, 0x30, 0x76, 0xa9, 0xf4, 0x86, 0x3c, 0x0f, 0x49, 0x55, 0x71, 0x14, 0x37, 0x2c, 0xf4, - 0x5b, 0xfa, 0x63, 0x12, 0x66, 0xa2, 0x0d, 0xd6, 0xff, 0xc5, 0x31, 0x21, 0x54, 0x61, 0x65, 0xdb, - 0x11, 0x32, 0x8c, 0x2a, 0xf2, 0xcd, 0xcf, 0x40, 0x66, 0x53, 0xdf, 0x6d, 0x11, 0x4f, 0xb3, 0xf3, - 0x5c, 0x25, 0x2b, 0xa7, 0x37, 0xf5, 0xdd, 0x26, 0xd6, 0x96, 0xae, 0x87, 0x02, 0x78, 0x76, 0x44, - 0x00, 0xeb, 0xd2, 0x3b, 0x50, 0x8e, 0x59, 0x3a, 0x66, 0x08, 0x3f, 0x9a, 0x04, 0xbe, 0x89, 0xb5, - 0x37, 0x77, 0x51, 0xa7, 0x37, 0xc6, 0x89, 0x22, 0x07, 0xd4, 0x95, 0x71, 0x03, 0xe8, 0x8f, 0xbd, - 0x40, 0x24, 0x8e, 0x10, 0x88, 0xd4, 0xcb, 0x3d, 0x1c, 0x97, 0x43, 0xdc, 0xce, 0x78, 0xdc, 0x86, - 0xe0, 0x4a, 0x37, 0x41, 0x1c, 0x9e, 0xf5, 0x19, 0xf5, 0x78, 0xe3, 0x02, 0xbc, 0x3d, 0xe6, 0x28, - 0x6f, 0x4d, 0x5d, 0xb3, 0x95, 0x17, 0xe4, 0x6d, 0xac, 0xdc, 0x77, 0xc9, 0x4d, 0x1e, 0x4a, 0x6e, - 0x3c, 0xe8, 0x90, 0xaf, 0x2e, 0xe8, 0xd0, 0xec, 0x48, 0xd0, 0x1f, 0x73, 0x70, 0xa2, 0x89, 0xb5, - 0xbb, 0x5d, 0x55, 0x71, 0xd0, 0x32, 0x3d, 0xb8, 0x71, 0x80, 0xe7, 0x20, 0x67, 0xa2, 0x9d, 0x56, - 0xf0, 0xa8, 0x67, 0x4d, 0xb4, 0xc3, 0x94, 0x82, 0x6c, 0x24, 0x06, 0xd9, 0x58, 0x5a, 0x08, 0xb9, - 0x7f, 0xda, 0x73, 0x3f, 0xb0, 0xab, 0x24, 0xd0, 0xab, 0x20, 0x30, 0xe3, 0xb9, 0x2d, 0x69, 0xf0, - 0x9f, 0x26, 0xd6, 0x56, 0xb6, 0x91, 0x62, 0x8f, 0x76, 0x70, 0x94, 0x0f, 0x52, 0xc8, 0x07, 0xde, - 0xf3, 0xa1, 0x6f, 0x57, 0x9a, 0x81, 0x33, 0x03, 0x13, 0xbe, 0x07, 0xbf, 0x73, 0x94, 0x57, 0xe6, - 0xdc, 0xe0, 0x49, 0xdd, 0xd4, 0xb5, 0x58, 0x7f, 0x02, 0x59, 0x30, 0x19, 0x9b, 0x05, 0xf7, 0x41, - 0x24, 0xac, 0xc6, 0x5c, 0xf3, 0x89, 0xb1, 0xae, 0x79, 0xc1, 0x44, 0x3b, 0xab, 0x91, 0x37, 0x7d, - 0x2d, 0x04, 0xbb, 0x3c, 0x48, 0xfd, 0x10, 0x16, 0xe9, 0x02, 0x48, 0xf1, 0xab, 0x3e, 0x21, 0xdf, - 0x70, 0x70, 0xd2, 0x17, 0x5b, 0x53, 0x6c, 0xc5, 0xc0, 0xfc, 0x2d, 0xc8, 0x29, 0x3d, 0x67, 0xcb, - 0xb2, 0x75, 0x67, 0x8f, 0x11, 0xd1, 0x10, 0x7e, 0xfc, 0xee, 0x46, 0xd1, 0x2d, 0x04, 0xcb, 0xac, - 0x62, 0xad, 0x3b, 0xb6, 0x6e, 0x6a, 0x72, 0x5f, 0x94, 0x7f, 0x03, 0xd2, 0x5d, 0x6a, 0x81, 0x92, - 0x94, 0xaf, 0x0b, 0xc3, 0x60, 0xd9, 0x0e, 0x8d, 0x1c, 0xa9, 0x1c, 0xac, 0x1a, 0xb8, 0x2a, 0xec, - 0x64, 0xf4, 0x8d, 0x11, 0x88, 0xc5, 0x41, 0x88, 0x4c, 0x57, 0x9a, 0xa5, 0xd7, 0x5a, 0x70, 0xca, - 0x07, 0xf3, 0x3d, 0x03, 0xb3, 0xde, 0x53, 0x2d, 0xff, 0xd0, 0x1f, 0x17, 0xcc, 0x3f, 0x52, 0x4c, - 0x47, 0xa2, 0x0a, 0xba, 0x29, 0xdd, 0xa0, 0xa8, 0x82, 0x53, 0x23, 0x0f, 0xfb, 0x17, 0x1c, 0xe4, - 0x9b, 0x58, 0x5b, 0xd3, 0x4d, 0x92, 0x84, 0xc7, 0x0f, 0xd9, 0xeb, 0x04, 0x25, 0x4d, 0x6c, 0x12, - 0xb4, 0x44, 0x25, 0xd9, 0x28, 0x1d, 0xec, 0x97, 0x33, 0x2c, 0xb3, 0xf1, 0x9f, 0xfb, 0xe5, 0x93, - 0x7b, 0x8a, 0xb1, 0xbd, 0x24, 0x79, 0x42, 0x92, 0x9c, 0x61, 0xd9, 0x8e, 0x59, 0x2d, 0x18, 0x84, - 0x36, 0xe5, 0x41, 0xf3, 0xfc, 0x92, 0xce, 0xc0, 0xe9, 0xc0, 0xd0, 0x0f, 0xd4, 0x57, 0x1c, 0xad, - 0x04, 0x77, 0xcd, 0xee, 0x2b, 0x04, 0x70, 0x71, 0x18, 0x80, 0x5f, 0x4b, 0xfa, 0x9e, 0xb9, 0xb5, - 0xa4, 0x3f, 0xe1, 0x83, 0xf8, 0x21, 0x49, 0x3b, 0x36, 0xda, 0x4d, 0x2f, 0x9b, 0x6a, 0x54, 0xef, - 0x7b, 0x5c, 0x54, 0xc3, 0xaf, 0x8c, 0xc4, 0x0b, 0xbe, 0x32, 0x92, 0x2f, 0xf0, 0xca, 0xe0, 0xcf, - 0x01, 0xf4, 0x08, 0x7e, 0xe6, 0x4a, 0x8a, 0xb6, 0x48, 0xb9, 0x9e, 0xc7, 0x48, 0xbf, 0x6b, 0x4c, - 0x07, 0xbb, 0x46, 0xbf, 0x21, 0xcc, 0x44, 0x34, 0x84, 0xd9, 0x23, 0xf4, 0x21, 0xb9, 0x97, 0xdb, - 0x10, 0x92, 0x9a, 0x6f, 0xf5, 0xec, 0x0e, 0x12, 0xc0, 0xad, 0xf9, 0x74, 0x44, 0x5a, 0xb5, 0x76, - 0x4f, 0xdf, 0x26, 0x97, 0x41, 0x9e, 0xb5, 0x6a, 0xee, 0x90, 0x5c, 0x9f, 0x34, 0x9d, 0xb6, 0x14, - 0xbc, 0x25, 0x14, 0xdc, 0x97, 0x90, 0xa5, 0xa2, 0xb7, 0x14, 0xbc, 0xb5, 0x74, 0x6b, 0x38, 0xab, - 0x16, 0x06, 0x1e, 0x65, 0xd1, 0xa9, 0x22, 0xdd, 0x83, 0x4b, 0xa3, 0x25, 0x8e, 0xd9, 0x43, 0x7e, - 0xcb, 0xc1, 0x29, 0x72, 0x04, 0xed, 0x9e, 0x89, 0x36, 0x14, 0x6c, 0xbc, 0xb2, 0xe3, 0x76, 0x65, - 0x98, 0x98, 0x69, 0xbf, 0x5e, 0x0c, 0x78, 0x27, 0xcd, 0xc1, 0xec, 0xd0, 0xa4, 0x07, 0xbf, 0xfe, - 0x79, 0x1e, 0x12, 0x4d, 0xac, 0xf1, 0xeb, 0x90, 0xeb, 0x3f, 0xd7, 0x23, 0x12, 0x3b, 0xf8, 0xd0, - 0x15, 0x2f, 0x8d, 0x5e, 0xf7, 0xb9, 0x7d, 0x1f, 0x4e, 0x47, 0x9d, 0xe3, 0x4a, 0xa4, 0x7a, 0x84, - 0xa4, 0x78, 0x73, 0x5c, 0x49, 0x7f, 0x4b, 0x07, 0x8a, 0x91, 0x6f, 0xb4, 0x2b, 0xe3, 0x5a, 0xaa, - 0x8b, 0x8b, 0x63, 0x8b, 0xfa, 0xbb, 0x22, 0x38, 0x19, 0x7e, 0x56, 0x5c, 0x88, 0xb4, 0x12, 0x92, - 0x12, 0xaf, 0x8f, 0x23, 0x15, 0xdc, 0x26, 0xdc, 0x85, 0x47, 0x6f, 0x13, 0x92, 0x8a, 0xd9, 0x26, - 0xae, 0x1f, 0x7e, 0x17, 0xf2, 0xc1, 0xbe, 0x77, 0x3e, 0x52, 0x39, 0x20, 0x21, 0x56, 0x0e, 0x93, - 0xf0, 0x4d, 0xdf, 0x03, 0x08, 0x34, 0xac, 0xe5, 0x48, 0xbd, 0xbe, 0x80, 0x78, 0xf9, 0x10, 0x01, - 0xdf, 0xee, 0x07, 0x30, 0x13, 0xd7, 0x85, 0x5e, 0x1f, 0xe1, 0xdc, 0x90, 0xb4, 0xf8, 0xbf, 0xa3, - 0x48, 0xfb, 0xdb, 0xdf, 0x87, 0xc2, 0x40, 0xcf, 0x77, 0x7e, 0x84, 0x15, 0x26, 0x22, 0x5e, 0x39, - 0x54, 0x24, 0x68, 0x7d, 0xa0, 0x09, 0x8b, 0xb6, 0x1e, 0x14, 0x89, 0xb1, 0x1e, 0xd9, 0x10, 0xad, - 0x41, 0xd6, 0x6f, 0x7c, 0xce, 0x45, 0xaa, 0x79, 0xcb, 0xe2, 0xc5, 0x91, 0xcb, 0xc1, 0x20, 0x07, - 0x7a, 0x91, 0xe8, 0x20, 0xf7, 0x05, 0x62, 0x82, 0x3c, 0xdc, 0x22, 0xf0, 0x9f, 0x70, 0x30, 0x37, - 0xaa, 0x3f, 0xb8, 0x19, 0x5f, 0x96, 0xa2, 0x35, 0xc4, 0xd7, 0x8e, 0xaa, 0xe1, 0xfb, 0xd2, 0x86, - 0x13, 0xa1, 0x4b, 0x60, 0x21, 0x9a, 0x9c, 0x01, 0x21, 0xf1, 0xda, 0x18, 0x42, 0xde, 0x1e, 0x8d, - 0xdb, 0x4f, 0x7e, 0x2d, 0x4d, 0x3c, 0x39, 0x28, 0x71, 0x4f, 0x0f, 0x4a, 0xdc, 0x2f, 0x07, 0x25, - 0xee, 0xb3, 0x67, 0xa5, 0x89, 0xa7, 0xcf, 0x4a, 0x13, 0x3f, 0x3d, 0x2b, 0x4d, 0xbc, 0x77, 0x29, - 0x70, 0x3f, 0xaf, 0x58, 0xd8, 0xd8, 0xf0, 0x7e, 0xbb, 0x55, 0x6b, 0xbb, 0xec, 0x37, 0x5c, 0x7a, - 0x47, 0xb7, 0xd3, 0xf4, 0x37, 0xd9, 0xff, 0xfe, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x47, 0x63, 0xda, - 0xd1, 0x5d, 0x16, 0x00, 0x00, + // 1513 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x58, 0xcd, 0x6f, 0x1b, 0x45, + 0x14, 0xcf, 0xc6, 0xdf, 0xcf, 0x26, 0x4d, 0xb7, 0x6e, 0xe2, 0x6c, 0x5a, 0x3b, 0xdd, 0xf4, 0xc3, + 0xfd, 0xb2, 0x1b, 0x03, 0x11, 0x98, 0x53, 0x9c, 0x22, 0x91, 0x0a, 0x43, 0xe4, 0xa8, 0x8d, 0x40, + 0x95, 0xac, 0xb5, 0x77, 0xb2, 0x59, 0xd5, 0xbb, 0x6b, 0x76, 0xd6, 0x4d, 0x72, 0xe0, 0x02, 0x12, + 0x12, 0x9c, 0xb8, 0xf2, 0x07, 0x20, 0x01, 0x07, 0xe8, 0x81, 0x03, 0xc7, 0x1e, 0x2b, 0x71, 0xa9, + 0x38, 0x71, 0x0a, 0x90, 0x22, 0x95, 0x1b, 0x12, 0x47, 0x4e, 0x68, 0x66, 0x76, 0xd7, 0xeb, 0xf5, + 0xae, 0xe3, 0x24, 0x54, 0x1c, 0xb8, 0x24, 0x3b, 0xf3, 0x3e, 0xe6, 0xfd, 0x7e, 0xef, 0xcd, 0xcc, + 0x1b, 0xc3, 0x5c, 0xdb, 0xc0, 0xda, 0x8e, 0x84, 0xb5, 0x32, 0xfd, 0xf3, 0x70, 0xa9, 0x6c, 0xed, + 0x96, 0xba, 0xa6, 0x61, 0x19, 0xfc, 0xb4, 0x23, 0x2a, 0xd1, 0x3f, 0x0f, 0x97, 0x84, 0x3c, 0x99, + 0x31, 0x70, 0xb9, 0x25, 0x61, 0x54, 0x7e, 0xb8, 0xd4, 0x42, 0x96, 0xb4, 0x54, 0x6e, 0x1b, 0xaa, + 0xce, 0x2c, 0x84, 0x59, 0x5b, 0xae, 0x61, 0x85, 0x78, 0xd2, 0xb0, 0x62, 0x0b, 0xb2, 0x8a, 0xa1, + 0x18, 0xf4, 0xb3, 0x4c, 0xbe, 0xec, 0xd9, 0x73, 0xc3, 0x6b, 0xef, 0x75, 0x11, 0xb6, 0xa5, 0x73, + 0xcc, 0x59, 0x93, 0x99, 0xb1, 0x81, 0x2d, 0x3a, 0x2d, 0x69, 0xaa, 0x6e, 0x94, 0xe9, 0x5f, 0x36, + 0x25, 0xfe, 0xce, 0x41, 0xa6, 0x8e, 0x95, 0x0d, 0xcb, 0x30, 0xd1, 0xaa, 0x21, 0x23, 0x7e, 0x06, + 0xe2, 0x18, 0xe9, 0x32, 0x32, 0x73, 0xdc, 0x02, 0x57, 0x4c, 0x35, 0xec, 0x11, 0xbf, 0x0c, 0x53, + 0x64, 0xb5, 0x66, 0x6b, 0xcf, 0x42, 0xcd, 0xb6, 0x21, 0xa3, 0xdc, 0xe4, 0x02, 0x57, 0xcc, 0xd4, + 0xa6, 0x0f, 0xf6, 0x0b, 0x99, 0xcd, 0x95, 0x8d, 0x7a, 0x6d, 0xcf, 0xa2, 0x1e, 0x1a, 0x19, 0xa2, + 0xe7, 0x8c, 0xf8, 0xbb, 0x30, 0xa3, 0xea, 0xd8, 0x92, 0x74, 0x4b, 0x95, 0x2c, 0xd4, 0xec, 0x22, + 0x53, 0x53, 0x31, 0x56, 0x0d, 0x3d, 0x17, 0x5b, 0xe0, 0x8a, 0xe9, 0x4a, 0xbe, 0xe4, 0xa7, 0xab, + 0xb4, 0xd2, 0x6e, 0x23, 0x8c, 0x57, 0x0d, 0x7d, 0x4b, 0x55, 0x1a, 0x67, 0x3d, 0xd6, 0xeb, 0xae, + 0x71, 0xf5, 0xc2, 0x47, 0xcf, 0x1f, 0x5d, 0xb3, 0x63, 0xfb, 0xec, 0xf9, 0xa3, 0x6b, 0xa7, 0x29, + 0x15, 0x5e, 0x24, 0x77, 0xa2, 0xc9, 0xc8, 0x74, 0xf4, 0x4e, 0x34, 0x19, 0x9d, 0x8e, 0x89, 0x9b, + 0x90, 0xf5, 0xca, 0x1a, 0x08, 0x77, 0x0d, 0x1d, 0x23, 0x7e, 0x11, 0x12, 0x04, 0x4b, 0x53, 0x95, + 0x29, 0xdc, 0x68, 0x0d, 0x0e, 0xf6, 0x0b, 0x71, 0xa2, 0xb2, 0x76, 0xbb, 0x11, 0x27, 0xa2, 0x35, + 0x99, 0x17, 0x20, 0xd9, 0xde, 0x46, 0xed, 0x07, 0xb8, 0xa7, 0x31, 0xd0, 0x0d, 0x77, 0x2c, 0x3e, + 0x9e, 0x84, 0x99, 0x3a, 0x56, 0xd6, 0xfa, 0x41, 0xae, 0x1a, 0xba, 0x65, 0x4a, 0x6d, 0x2b, 0x94, + 0xc9, 0x2c, 0xc4, 0x24, 0x59, 0x53, 0x75, 0xea, 0x2b, 0xd5, 0x60, 0x03, 0x6f, 0x24, 0x91, 0xd0, + 0x48, 0xb2, 0x10, 0xeb, 0x48, 0x2d, 0xd4, 0xc9, 0x45, 0x99, 0x29, 0x1d, 0xf0, 0x45, 0x88, 0x68, + 0x58, 0xa1, 0x7c, 0x66, 0x6a, 0x33, 0x7f, 0xef, 0x17, 0xf8, 0x86, 0xb4, 0xe3, 0x84, 0x51, 0x47, + 0x18, 0x4b, 0x0a, 0x6a, 0x10, 0x15, 0x7e, 0x0b, 0x62, 0x5b, 0x3d, 0x5d, 0xc6, 0xb9, 0xf8, 0x42, + 0xa4, 0x98, 0xae, 0xcc, 0x95, 0xec, 0xf2, 0x20, 0x85, 0x59, 0xb2, 0x0b, 0xb3, 0xb4, 0x6a, 0xa8, + 0x7a, 0xed, 0xd5, 0x27, 0xfb, 0x85, 0x89, 0x6f, 0x7e, 0x29, 0x14, 0x15, 0xd5, 0xda, 0xee, 0xb5, + 0x4a, 0x6d, 0x43, 0xb3, 0x6b, 0xc9, 0xfe, 0x77, 0x13, 0xcb, 0x0f, 0xec, 0xba, 0x23, 0x06, 0xf8, + 0xab, 0xe7, 0x8f, 0xae, 0x71, 0x0d, 0xe6, 0xbe, 0x7a, 0xdd, 0x97, 0x9d, 0x79, 0x27, 0x3b, 0x01, + 0x3c, 0x89, 0xef, 0x40, 0x3e, 0x58, 0xe2, 0x66, 0x29, 0x07, 0x09, 0x49, 0x96, 0x4d, 0x84, 0xb1, + 0x4d, 0xa5, 0x33, 0xe4, 0x79, 0x88, 0xca, 0x92, 0x25, 0xd9, 0x69, 0xa1, 0xdf, 0xe2, 0x9f, 0x93, + 0x30, 0x1b, 0xec, 0xb0, 0xf2, 0x3f, 0xce, 0x09, 0xa1, 0x0a, 0x4b, 0x1d, 0x2b, 0x97, 0x60, 0x54, + 0x91, 0x6f, 0x7e, 0x16, 0x12, 0x5b, 0xea, 0x6e, 0x93, 0x44, 0x9a, 0x5c, 0xe0, 0x8a, 0xc9, 0x46, + 0x7c, 0x4b, 0xdd, 0xad, 0x63, 0xa5, 0x7a, 0xc3, 0x97, 0xc0, 0x73, 0x23, 0x12, 0x58, 0x11, 0xdf, + 0x85, 0x42, 0x88, 0xe8, 0x98, 0x29, 0xfc, 0x78, 0x12, 0xf8, 0x3a, 0x56, 0xde, 0xdc, 0x45, 0xed, + 0xde, 0x18, 0x3b, 0x8a, 0x6c, 0x50, 0x5b, 0xc7, 0x4e, 0xa0, 0x3b, 0x76, 0x12, 0x11, 0x39, 0x42, + 0x22, 0x62, 0x2f, 0x76, 0x73, 0x5c, 0xf1, 0x71, 0x3b, 0xeb, 0x70, 0xeb, 0x83, 0x2b, 0xde, 0x02, + 0x61, 0x78, 0xd6, 0x65, 0xd4, 0xe1, 0x8d, 0xf3, 0xf0, 0xf6, 0x98, 0xa3, 0xbc, 0xd5, 0x55, 0xc5, + 0x94, 0x4e, 0xc8, 0xdb, 0x58, 0xb5, 0x6f, 0x93, 0x1b, 0x3d, 0x94, 0xdc, 0x70, 0xd0, 0xbe, 0x58, + 0x6d, 0xd0, 0xbe, 0xd9, 0x91, 0xa0, 0x3f, 0xe1, 0x60, 0xaa, 0x8e, 0x95, 0xbb, 0x5d, 0x59, 0xb2, + 0xd0, 0x0a, 0xdd, 0xb8, 0x61, 0x80, 0xe7, 0x21, 0xa5, 0xa3, 0x9d, 0xa6, 0x77, 0xab, 0x27, 0x75, + 0xb4, 0xc3, 0x8c, 0xbc, 0x6c, 0x44, 0x06, 0xd9, 0xa8, 0x2e, 0xfa, 0xc2, 0x3f, 0xe3, 0x84, 0xef, + 0x59, 0x55, 0xcc, 0xd1, 0xab, 0xc0, 0x33, 0xe3, 0x84, 0x2d, 0x2a, 0xf0, 0x52, 0x1d, 0x2b, 0xab, + 0x1d, 0x24, 0x99, 0xa3, 0x03, 0x1c, 0x15, 0x83, 0xe8, 0x8b, 0x81, 0x77, 0x62, 0xe8, 0xfb, 0x15, + 0x67, 0xe1, 0xec, 0xc0, 0x84, 0x1b, 0xc1, 0x1f, 0x1c, 0xe5, 0x95, 0x05, 0x37, 0xb8, 0x53, 0xb7, + 0x54, 0x25, 0x34, 0x1e, 0x4f, 0x15, 0x4c, 0x86, 0x56, 0xc1, 0x7d, 0x10, 0x08, 0xab, 0x21, 0xd7, + 0x7c, 0x64, 0xac, 0x6b, 0x3e, 0xa7, 0xa3, 0x9d, 0xb5, 0xc0, 0x9b, 0xbe, 0xec, 0x83, 0x5d, 0x18, + 0xa4, 0x7e, 0x08, 0x8b, 0x78, 0x11, 0xc4, 0x70, 0xa9, 0x4b, 0xc8, 0x77, 0x1c, 0x9c, 0x72, 0xd5, + 0xd6, 0x25, 0x53, 0xd2, 0x30, 0xbf, 0x0c, 0x29, 0xa9, 0x67, 0x6d, 0x1b, 0xa6, 0x6a, 0xed, 0x31, + 0x22, 0x6a, 0xb9, 0x9f, 0xbe, 0xbf, 0x99, 0xb5, 0x0f, 0x82, 0x15, 0x76, 0x62, 0x6d, 0x58, 0xa6, + 0xaa, 0x2b, 0x8d, 0xbe, 0x2a, 0xff, 0x06, 0xc4, 0xbb, 0xd4, 0x03, 0x25, 0x29, 0x5d, 0xc9, 0x0d, + 0x83, 0x65, 0x2b, 0xd4, 0x52, 0xe4, 0xe4, 0x60, 0xa7, 0x81, 0x6d, 0xc2, 0x76, 0x46, 0xdf, 0x19, + 0x81, 0x98, 0x1d, 0x84, 0xc8, 0x6c, 0xc5, 0x39, 0x7a, 0xad, 0x79, 0xa7, 0x5c, 0x30, 0x3f, 0x30, + 0x30, 0x1b, 0x3d, 0xd9, 0x70, 0x37, 0xfd, 0x71, 0xc1, 0xfc, 0x2b, 0x87, 0xe9, 0x48, 0x54, 0xde, + 0x30, 0xc5, 0x9b, 0x14, 0x95, 0x77, 0x6a, 0xe4, 0x66, 0xff, 0x92, 0x83, 0x74, 0x1d, 0x2b, 0xeb, + 0xaa, 0x4e, 0x8a, 0xf0, 0xf8, 0x29, 0x7b, 0x9d, 0xa0, 0xa4, 0x85, 0x4d, 0x92, 0x16, 0x29, 0x46, + 0x6b, 0xf9, 0x83, 0xfd, 0x42, 0x82, 0x55, 0x36, 0xfe, 0x6b, 0xbf, 0x70, 0x6a, 0x4f, 0xd2, 0x3a, + 0x55, 0xd1, 0x51, 0x12, 0x1b, 0x09, 0x56, 0xed, 0x98, 0x9d, 0x05, 0x83, 0xd0, 0xa6, 0x1d, 0x68, + 0x4e, 0x5c, 0xe2, 0x59, 0x38, 0xe3, 0x19, 0xba, 0x89, 0xfa, 0x9a, 0xa3, 0x27, 0xc1, 0x5d, 0xbd, + 0xfb, 0x1f, 0x02, 0xb8, 0x34, 0x0c, 0xc0, 0x3d, 0x4b, 0xfa, 0x91, 0xd9, 0x67, 0x49, 0x7f, 0xc2, + 0x05, 0xf1, 0x63, 0x94, 0x76, 0x6c, 0xb4, 0x9b, 0x5e, 0xd1, 0xe5, 0xa0, 0xde, 0xf7, 0xb8, 0xa8, + 0x86, 0x5f, 0x19, 0x91, 0x13, 0xbe, 0x32, 0xa2, 0x27, 0x78, 0x65, 0xf0, 0xe7, 0x01, 0x7a, 0x04, + 0x3f, 0x0b, 0x25, 0x46, 0x5b, 0xa4, 0x54, 0xcf, 0x61, 0xa4, 0xdf, 0x35, 0xc6, 0xbd, 0x5d, 0xa3, + 0xdb, 0x10, 0x26, 0x02, 0x1a, 0xc2, 0xe4, 0x11, 0xfa, 0x90, 0xd4, 0x8b, 0x6d, 0x08, 0xc9, 0x99, + 0x6f, 0xf4, 0xcc, 0x36, 0xca, 0x81, 0x7d, 0xe6, 0xd3, 0x11, 0x69, 0xd5, 0x5a, 0x3d, 0xb5, 0x43, + 0x2e, 0x83, 0x34, 0x6b, 0xd5, 0xec, 0x21, 0xb9, 0x3e, 0x69, 0x39, 0x6d, 0x4b, 0x78, 0x3b, 0x97, + 0xb1, 0x5f, 0x42, 0x86, 0x8c, 0xde, 0x92, 0xf0, 0x76, 0x75, 0x79, 0xb8, 0xaa, 0x16, 0x07, 0x1e, + 0x65, 0xc1, 0xa5, 0x22, 0xde, 0x83, 0xcb, 0xa3, 0x35, 0x8e, 0xd9, 0x43, 0x7e, 0xcb, 0xc1, 0x69, + 0xb2, 0x05, 0xcd, 0x9e, 0x8e, 0x36, 0x25, 0xac, 0x9d, 0x6c, 0xbb, 0x2d, 0xc3, 0x54, 0x47, 0xb2, + 0x10, 0xb6, 0x9a, 0x83, 0xf7, 0x21, 0x2d, 0xcc, 0xb7, 0xa9, 0xc4, 0xbe, 0x15, 0x33, 0x9d, 0xfe, + 0x48, 0xae, 0x5e, 0x1d, 0x66, 0x65, 0xc6, 0x3d, 0x2c, 0x06, 0x42, 0x13, 0xe7, 0x61, 0x6e, 0x68, + 0xd2, 0xc1, 0x5e, 0xf9, 0x22, 0x0d, 0x91, 0x3a, 0x56, 0xf8, 0x0d, 0x48, 0xf5, 0xdf, 0xea, 0x01, + 0x55, 0xed, 0x7d, 0xe5, 0x0a, 0x97, 0x47, 0xcb, 0x5d, 0x62, 0x3f, 0x80, 0x33, 0x41, 0x9b, 0xb8, + 0x18, 0x68, 0x1e, 0xa0, 0x29, 0xdc, 0x1a, 0x57, 0xd3, 0x5d, 0xd2, 0x82, 0x6c, 0xe0, 0x03, 0xed, + 0xea, 0xb8, 0x9e, 0x2a, 0xc2, 0xd2, 0xd8, 0xaa, 0xee, 0xaa, 0x08, 0x4e, 0xf9, 0xdf, 0x14, 0x17, + 0x03, 0xbd, 0xf8, 0xb4, 0x84, 0x1b, 0xe3, 0x68, 0x79, 0x97, 0xf1, 0xb7, 0xe0, 0xc1, 0xcb, 0xf8, + 0xb4, 0x42, 0x96, 0x09, 0x6b, 0x86, 0xdf, 0x83, 0xb4, 0xb7, 0xe9, 0x5d, 0x08, 0x34, 0xf6, 0x68, + 0x08, 0xc5, 0xc3, 0x34, 0x5c, 0xd7, 0xf7, 0x00, 0x3c, 0xdd, 0x6a, 0x21, 0xd0, 0xae, 0xaf, 0x20, + 0x5c, 0x39, 0x44, 0xc1, 0xf5, 0xfb, 0x21, 0xcc, 0x86, 0xb5, 0xa0, 0x37, 0x46, 0x04, 0x37, 0xa4, + 0x2d, 0xbc, 0x72, 0x14, 0x6d, 0x77, 0xf9, 0xfb, 0x90, 0x19, 0x68, 0xf8, 0x2e, 0x8c, 0xf0, 0xc2, + 0x54, 0x84, 0xab, 0x87, 0xaa, 0x78, 0xbd, 0x0f, 0x74, 0x60, 0xc1, 0xde, 0xbd, 0x2a, 0x21, 0xde, + 0x03, 0xbb, 0xa1, 0x75, 0x48, 0xba, 0x5d, 0xcf, 0xf9, 0x40, 0x33, 0x47, 0x2c, 0x5c, 0x1a, 0x29, + 0xf6, 0x26, 0xd9, 0xd3, 0x88, 0x04, 0x27, 0xb9, 0xaf, 0x10, 0x92, 0xe4, 0xe1, 0xfe, 0x80, 0xff, + 0x94, 0x83, 0xf9, 0x51, 0xcd, 0xc1, 0xad, 0xf0, 0x63, 0x29, 0xd8, 0x42, 0x78, 0xed, 0xa8, 0x16, + 0x6e, 0x2c, 0x2d, 0x98, 0xf2, 0xdd, 0x00, 0x8b, 0xc1, 0xe4, 0x0c, 0x28, 0x09, 0xd7, 0xc7, 0x50, + 0x72, 0xd6, 0xa8, 0xdd, 0x7e, 0xf2, 0x5b, 0x7e, 0xe2, 0xc9, 0x41, 0x9e, 0x7b, 0x7a, 0x90, 0xe7, + 0x7e, 0x3d, 0xc8, 0x73, 0x9f, 0x3f, 0xcb, 0x4f, 0x3c, 0x7d, 0x96, 0x9f, 0xf8, 0xf9, 0x59, 0x7e, + 0xe2, 0xfd, 0xcb, 0x9e, 0xcb, 0x79, 0xd5, 0xc0, 0xda, 0xa6, 0xf3, 0xc3, 0xad, 0x5c, 0xde, 0x65, + 0x3f, 0xe0, 0xd2, 0x0b, 0xba, 0x15, 0xa7, 0x3f, 0xc8, 0xbe, 0xfc, 0x4f, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xf4, 0x27, 0xa9, 0xed, 0x5a, 0x16, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -3264,23 +3266,10 @@ func (m *MsgPruneWasmCodes) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.CodeIDs) > 0 { - dAtA10 := make([]byte, len(m.CodeIDs)*10) - var j9 int - for _, num := range m.CodeIDs { - for num >= 1<<7 { - dAtA10[j9] = uint8(uint64(num)&0x7f | 0x80) - num >>= 7 - j9++ - } - dAtA10[j9] = uint8(num) - j9++ - } - i -= j9 - copy(dAtA[i:], dAtA10[:j9]) - i = encodeVarintTx(dAtA, i, uint64(j9)) + if m.LatestCodeID != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.LatestCodeID)) i-- - dAtA[i] = 0x12 + dAtA[i] = 0x10 } if len(m.Authority) > 0 { i -= len(m.Authority) @@ -3832,12 +3821,8 @@ func (m *MsgPruneWasmCodes) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } - if len(m.CodeIDs) > 0 { - l = 0 - for _, e := range m.CodeIDs { - l += sovTx(uint64(e)) - } - n += 1 + sovTx(uint64(l)) + l + if m.LatestCodeID != 0 { + n += 1 + sovTx(uint64(m.LatestCodeID)) } return n } @@ -7349,80 +7334,23 @@ func (m *MsgPruneWasmCodes) Unmarshal(dAtA []byte) error { m.Authority = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: - if wireType == 0 { - var v uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.CodeIDs = append(m.CodeIDs, v) - } else if wireType == 2 { - var packedLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - packedLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if packedLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + packedLen - if postIndex < 0 { - return ErrInvalidLengthTx + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LatestCodeID", wireType) + } + m.LatestCodeID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx } - if postIndex > l { + if iNdEx >= 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.CodeIDs) == 0 { - m.CodeIDs = make([]uint64, 0, elementCount) - } - for iNdEx < postIndex { - var v uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.CodeIDs = append(m.CodeIDs, v) + b := dAtA[iNdEx] + iNdEx++ + m.LatestCodeID |= uint64(b&0x7F) << shift + if b < 0x80 { + break } - } else { - return fmt.Errorf("proto: wrong wireType = %d for field CodeIDs", wireType) } default: iNdEx = preIndex diff --git a/x/wasm/types/tx_test.go b/x/wasm/types/tx_test.go index 4edf6e4292..597ae8fed7 100644 --- a/x/wasm/types/tx_test.go +++ b/x/wasm/types/tx_test.go @@ -1139,24 +1139,24 @@ func TestMsgPruneWasmCodesValidation(t *testing.T) { }{ "all good": { src: MsgPruneWasmCodes{ - Authority: goodAddress, - CodeIDs: []uint64{1}, + Authority: goodAddress, + LatestCodeID: 5, }, }, "bad authority": { src: MsgPruneWasmCodes{ - Authority: badAddress, - CodeIDs: []uint64{1}, + Authority: badAddress, + LatestCodeID: 5, }, expErr: true, }, "empty authority": { src: MsgPruneWasmCodes{ - CodeIDs: []uint64{1}, + LatestCodeID: 5, }, expErr: true, }, - "empty code ids": { + "empty code id": { src: MsgPruneWasmCodes{ Authority: goodAddress, }, From b84c0f430f61f439f1682264d1928ac8fd5b899e Mon Sep 17 00:00:00 2001 From: Pino' Surace Date: Tue, 20 Jun 2023 15:57:45 +0200 Subject: [PATCH 06/18] Add more tests --- x/wasm/keeper/keeper.go | 8 +- x/wasm/keeper/msg_server_integration_test.go | 152 +++++++++++++++---- 2 files changed, 127 insertions(+), 33 deletions(-) diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index 1cdef26809..7d65cd035f 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -1231,7 +1231,7 @@ func (k Keeper) PruneWasmCodes(ctx sdk.Context, codeID uint64) error { } if k.IsPinnedCode(ctx, c) { - pinnedCodesHash[string(info.CodeHash)] = struct{}{} + pinnedCodesHash[hex.Dump(info.CodeHash)] = struct{}{} continue } unpinnedCodes = append(unpinnedCodes, c) @@ -1243,14 +1243,12 @@ func (k Keeper) PruneWasmCodes(ctx sdk.Context, codeID uint64) error { continue } - if _, found := pinnedCodesHash[string(info.CodeHash)]; found { + if _, found := pinnedCodesHash[hex.Dump(info.CodeHash)]; found { continue } - if err := k.wasmVM.RemoveCode(info.CodeHash); err != nil { - continue - } k.deleteCodeInfo(ctx, code) + _ = k.wasmVM.RemoveCode(info.CodeHash) } return nil } diff --git a/x/wasm/keeper/msg_server_integration_test.go b/x/wasm/keeper/msg_server_integration_test.go index 16c25d3797..89d73f774f 100644 --- a/x/wasm/keeper/msg_server_integration_test.go +++ b/x/wasm/keeper/msg_server_integration_test.go @@ -854,7 +854,7 @@ func TestUpdateInstantiateConfig(t *testing.T) { } } -func TestPruneWasmCodes(t *testing.T) { +func TestPruneWasmCodesAuth(t *testing.T) { wasmApp := app.Setup(t) ctx := wasmApp.BaseApp.NewContext(false, tmproto.Header{}) @@ -894,36 +894,14 @@ func TestPruneWasmCodes(t *testing.T) { } for name, spec := range specs { t.Run(name, func(t *testing.T) { - // setup - _, _, sender := testdata.KeyTestPubAddr() - msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) { - m.WASMByteCode = wasmContract - m.Sender = sender.String() - }) - - // store code - rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg) - require.NoError(t, err) - var result types.MsgStoreCodeResponse - require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &result)) - - if spec.pinCode { - // pin code - msgPin := &types.MsgPinCodes{ - Authority: authority, - CodeIDs: []uint64{result.CodeID}, - } - _, err = wasmApp.MsgServiceRouter().Handler(msgPin)(ctx, msgPin) - require.NoError(t, err) - assert.True(t, wasmApp.WasmKeeper.IsPinnedCode(ctx, result.CodeID)) - } + codeID := setupWasmCode(t, authority, ctx, wasmApp, wasmContract, spec.pinCode) // when msgPruneCodes := &types.MsgPruneWasmCodes{ Authority: spec.addr, - LatestCodeID: result.CodeID, + LatestCodeID: 5, } - _, err = wasmApp.MsgServiceRouter().Handler(msgPruneCodes)(ctx, msgPruneCodes) + _, err := wasmApp.MsgServiceRouter().Handler(msgPruneCodes)(ctx, msgPruneCodes) // then if spec.expErr { @@ -933,10 +911,128 @@ func TestPruneWasmCodes(t *testing.T) { } if spec.expPruned { - assert.Nil(t, wasmApp.WasmKeeper.GetCodeInfo(ctx, result.CodeID)) + assert.Nil(t, wasmApp.WasmKeeper.GetCodeInfo(ctx, codeID)) } else { - assert.NotNil(t, wasmApp.WasmKeeper.GetCodeInfo(ctx, result.CodeID)) + assert.NotNil(t, wasmApp.WasmKeeper.GetCodeInfo(ctx, codeID)) + } + }) + } +} + +func TestPruneWasmCodes(t *testing.T) { + specs := map[string]struct { + wasmCode1 []byte + wasmCode2 []byte + pinCode1 bool + pinCode2 bool + expPruned1 bool + expPruned2 bool + }{ + "duplicate codes - both pinned": { + wasmCode1: wasmContract, + wasmCode2: wasmContract, + pinCode1: true, + pinCode2: true, + expPruned1: false, + expPruned2: false, + }, + "duplicate codes - only one pinned": { + wasmCode1: wasmContract, + wasmCode2: wasmContract, + pinCode1: true, + pinCode2: false, + expPruned1: false, + expPruned2: false, + }, + "duplicate codes - both unpinned": { + wasmCode1: wasmContract, + wasmCode2: wasmContract, + pinCode1: false, + pinCode2: false, + expPruned1: true, + expPruned2: true, + }, + "different codes - both pinned": { + wasmCode1: wasmContract, + wasmCode2: hackatomContract, + pinCode1: true, + pinCode2: true, + expPruned1: false, + expPruned2: false, + }, + "different codes - only one pinned": { + wasmCode1: wasmContract, + wasmCode2: hackatomContract, + pinCode1: true, + pinCode2: false, + expPruned1: false, + expPruned2: true, + }, + "different codes - both unpinned": { + wasmCode1: wasmContract, + wasmCode2: hackatomContract, + pinCode1: false, + pinCode2: false, + expPruned1: true, + expPruned2: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + wasmApp := app.Setup(t) + ctx := wasmApp.BaseApp.NewContext(false, tmproto.Header{}) + authority := wasmApp.WasmKeeper.GetAuthority() + + code1 := setupWasmCode(t, authority, ctx, wasmApp, spec.wasmCode1, spec.pinCode1) + code2 := setupWasmCode(t, authority, ctx, wasmApp, spec.wasmCode2, spec.pinCode2) + + // when + msgPruneCodes := &types.MsgPruneWasmCodes{ + Authority: authority, + LatestCodeID: 5, } + _, err := wasmApp.MsgServiceRouter().Handler(msgPruneCodes)(ctx, msgPruneCodes) + + // then + require.NoError(t, err) + + assertPruning(t, ctx, wasmApp, code1, spec.expPruned1) + assertPruning(t, ctx, wasmApp, code2, spec.expPruned2) }) } } + +func setupWasmCode(t *testing.T, authority string, ctx sdk.Context, wasmApp *app.WasmApp, wasmCode []byte, pin bool) uint64 { + // setup + _, _, sender := testdata.KeyTestPubAddr() + msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) { + m.WASMByteCode = wasmCode + m.Sender = sender.String() + }) + + // store code + rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg) + require.NoError(t, err) + var result types.MsgStoreCodeResponse + require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &result)) + + if pin { + // pin code + msgPin := &types.MsgPinCodes{ + Authority: authority, + CodeIDs: []uint64{result.CodeID}, + } + _, err = wasmApp.MsgServiceRouter().Handler(msgPin)(ctx, msgPin) + require.NoError(t, err) + assert.True(t, wasmApp.WasmKeeper.IsPinnedCode(ctx, result.CodeID)) + } + return result.CodeID +} + +func assertPruning(t *testing.T, ctx sdk.Context, wasmApp *app.WasmApp, codeID uint64, pruned bool) { + if pruned { + assert.Nil(t, wasmApp.WasmKeeper.GetCodeInfo(ctx, codeID)) + } else { + assert.NotNil(t, wasmApp.WasmKeeper.GetCodeInfo(ctx, codeID)) + } +} From 6924b1bbf2a96ab4bc90e736b11c6c57d31b1968 Mon Sep 17 00:00:00 2001 From: Pino' Surace Date: Thu, 22 Jun 2023 15:25:41 +0200 Subject: [PATCH 07/18] Fix prune wasm codes method --- docs/proto/proto-docs.md | 2 +- proto/cosmwasm/wasm/v1/tx.proto | 4 +- x/wasm/keeper/keeper.go | 73 ++++++++++++++++++++++----------- x/wasm/types/tx.pb.go | 4 +- 4 files changed, 54 insertions(+), 29 deletions(-) diff --git a/docs/proto/proto-docs.md b/docs/proto/proto-docs.md index bf287b7bb6..911c7532e1 100644 --- a/docs/proto/proto-docs.md +++ b/docs/proto/proto-docs.md @@ -1543,7 +1543,7 @@ MsgPruneWasmCodes is the MsgPruneWasmCodes request type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | `authority` | [string](#string) | | Authority is the address of the governance account. | -| `latest_code_id` | [uint64](#uint64) | | LatestCodeID references the greater limit until unpinned code ids will be pruned | +| `latest_code_id` | [uint64](#uint64) | | LatestCodeID is the upper limit so that all unpinned code ids code ids <= than latestCodeID will be pruned | diff --git a/proto/cosmwasm/wasm/v1/tx.proto b/proto/cosmwasm/wasm/v1/tx.proto index 5313dc93d6..b9ecbacb42 100644 --- a/proto/cosmwasm/wasm/v1/tx.proto +++ b/proto/cosmwasm/wasm/v1/tx.proto @@ -400,8 +400,8 @@ message MsgPruneWasmCodes { // Authority is the address of the governance account. string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; - // LatestCodeID references the upper limit until unpinned - // code ids will be pruned + // LatestCodeID is the upper limit so that all unpinned code ids + // code ids <= than latestCodeID will be pruned uint64 latest_code_id = 2 [ (gogoproto.customname) = "LatestCodeID" ]; } diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index 7d65cd035f..47c3e7b223 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -1219,36 +1219,61 @@ func (h DefaultWasmVMContractResponseHandler) Handle(ctx sdk.Context, contractAd return result, nil } -// PruneWasmCodes deletes code info for unpinned codes smaller than given code id. -func (k Keeper) PruneWasmCodes(ctx sdk.Context, codeID uint64) error { - pinnedCodesHash := make(map[string]struct{}, 0) - unpinnedCodes := make([]uint64, 0) - - for c := uint64(1); c < codeID; c++ { - info := k.GetCodeInfo(ctx, c) - if info == nil { - continue - } +// iteratePinnedCodes iterates over all pinned code ids in ascending order +func (k Keeper) iteratePinnedCodes(ctx sdk.Context, cb func(codeID uint64) bool) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.PinnedCodeIndexPrefix) + iter := store.Iterator(nil, nil) + defer iter.Close() - if k.IsPinnedCode(ctx, c) { - pinnedCodesHash[hex.Dump(info.CodeHash)] = struct{}{} - continue + l := len(types.PinnedCodeIndexPrefix) + for ; iter.Valid(); iter.Next() { + codeID := sdk.BigEndianToUint64(iter.Key()[l:]) + if cb(codeID) { + return } - unpinnedCodes = append(unpinnedCodes, c) } +} - for _, code := range unpinnedCodes { - info := k.GetCodeInfo(ctx, code) - if info == nil { - continue - } +// PruneWasmCodes deletes code info for unpinned codes <= than latestCodeID +func (k Keeper) PruneWasmCodes(ctx sdk.Context, latestCodeID uint64) error { + usedCodeIds := make(map[uint64]struct{}, 0) + usedChecksums := make(map[string]bool, 0) - if _, found := pinnedCodesHash[hex.Dump(info.CodeHash)]; found { - continue + // collect code ids used by contracts + k.IterateContractInfo(ctx, func(_ sdk.AccAddress, info types.ContractInfo) bool { + usedCodeIds[info.CodeID] = struct{}{} + return false + }) + + // collect pinned code ids + k.iteratePinnedCodes(ctx, func(codeID uint64) bool { + usedCodeIds[codeID] = struct{}{} + return false + }) + + // check if instances are used only by unpinned code ids <= latestCodeID + k.IterateCodeInfos(ctx, func(codeID uint64, info types.CodeInfo) bool { + if _, ok := usedCodeIds[codeID]; !ok && codeID <= latestCodeID { + usedChecksums[string(info.CodeHash)] = false + return false + } + usedChecksums[string(info.CodeHash)] = true + return false + }) + + // delete all unpinned code ids <= latestCodeID and all the + // instances used only by unpinned code ids <= latestCodeID + k.IterateCodeInfos(ctx, func(codeID uint64, info types.CodeInfo) bool { + if _, ok := usedCodeIds[codeID]; !ok && codeID <= latestCodeID { + k.deleteCodeInfo(ctx, codeID) + if !usedChecksums[string(info.CodeHash)] { + if err := k.wasmVM.RemoveCode(info.CodeHash); err != nil { + k.Logger(ctx).Error("failed to delete wasm file on disk", "checksum", info.CodeHash) + } + } } + return false + }) - k.deleteCodeInfo(ctx, code) - _ = k.wasmVM.RemoveCode(info.CodeHash) - } return nil } diff --git a/x/wasm/types/tx.pb.go b/x/wasm/types/tx.pb.go index 708a180d86..62a19a70ed 100644 --- a/x/wasm/types/tx.pb.go +++ b/x/wasm/types/tx.pb.go @@ -1293,8 +1293,8 @@ var xxx_messageInfo_MsgStoreAndInstantiateContractResponse proto.InternalMessage type MsgPruneWasmCodes struct { // Authority is the address of the governance account. Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` - // LatestCodeID references the greater limit until unpinned - // code ids will be pruned + // LatestCodeID is the upper limit so that all unpinned code ids + // code ids <= than latestCodeID will be pruned LatestCodeID uint64 `protobuf:"varint,2,opt,name=latest_code_id,json=latestCodeId,proto3" json:"latest_code_id,omitempty"` } From 6baca9b746f08a45c73b0139743f25df69c71b2b Mon Sep 17 00:00:00 2001 From: Pino' Surace Date: Thu, 22 Jun 2023 17:11:39 +0200 Subject: [PATCH 08/18] Fix test --- x/wasm/keeper/keeper.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index 47c3e7b223..dc9e3629bd 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -1225,9 +1225,8 @@ func (k Keeper) iteratePinnedCodes(ctx sdk.Context, cb func(codeID uint64) bool) iter := store.Iterator(nil, nil) defer iter.Close() - l := len(types.PinnedCodeIndexPrefix) for ; iter.Valid(); iter.Next() { - codeID := sdk.BigEndianToUint64(iter.Key()[l:]) + codeID := sdk.BigEndianToUint64(iter.Key()) if cb(codeID) { return } From b4dc69be6555400aafa39dec71455dc4a606e0f6 Mon Sep 17 00:00:00 2001 From: Pino' Surace Date: Thu, 22 Jun 2023 17:34:22 +0200 Subject: [PATCH 09/18] Fix integration test --- x/wasm/keeper/msg_server_integration_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/wasm/keeper/msg_server_integration_test.go b/x/wasm/keeper/msg_server_integration_test.go index 89d73f774f..b4a5e5a231 100644 --- a/x/wasm/keeper/msg_server_integration_test.go +++ b/x/wasm/keeper/msg_server_integration_test.go @@ -942,7 +942,7 @@ func TestPruneWasmCodes(t *testing.T) { pinCode1: true, pinCode2: false, expPruned1: false, - expPruned2: false, + expPruned2: true, }, "duplicate codes - both unpinned": { wasmCode1: wasmContract, From 7ba798e59034d168f123f7a8a5d10ad0deff20e6 Mon Sep 17 00:00:00 2001 From: Pino' Surace Date: Thu, 22 Jun 2023 19:20:19 +0200 Subject: [PATCH 10/18] Fix bug and improve tests --- x/wasm/keeper/keeper.go | 9 +- x/wasm/keeper/msg_server_integration_test.go | 128 +++++++++++-------- 2 files changed, 86 insertions(+), 51 deletions(-) diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index dc9e3629bd..5a1d599cf3 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -1219,6 +1219,11 @@ func (h DefaultWasmVMContractResponseHandler) Handle(ctx sdk.Context, contractAd return result, nil } +// GetByteCodeByChecksum queries the wasm code by checksum +func (k Keeper) GetByteCodeByChecksum(ctx sdk.Context, checksum wasmvm.Checksum) ([]byte, error) { + return k.wasmVM.GetCode(checksum) +} + // iteratePinnedCodes iterates over all pinned code ids in ascending order func (k Keeper) iteratePinnedCodes(ctx sdk.Context, cb func(codeID uint64) bool) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.PinnedCodeIndexPrefix) @@ -1253,7 +1258,9 @@ func (k Keeper) PruneWasmCodes(ctx sdk.Context, latestCodeID uint64) error { // check if instances are used only by unpinned code ids <= latestCodeID k.IterateCodeInfos(ctx, func(codeID uint64, info types.CodeInfo) bool { if _, ok := usedCodeIds[codeID]; !ok && codeID <= latestCodeID { - usedChecksums[string(info.CodeHash)] = false + if _, found := usedChecksums[string(info.CodeHash)]; !found { + usedChecksums[string(info.CodeHash)] = false + } return false } usedChecksums[string(info.CodeHash)] = true diff --git a/x/wasm/keeper/msg_server_integration_test.go b/x/wasm/keeper/msg_server_integration_test.go index b4a5e5a231..1bb9327fa4 100644 --- a/x/wasm/keeper/msg_server_integration_test.go +++ b/x/wasm/keeper/msg_server_integration_test.go @@ -894,7 +894,7 @@ func TestPruneWasmCodesAuth(t *testing.T) { } for name, spec := range specs { t.Run(name, func(t *testing.T) { - codeID := setupWasmCode(t, authority, ctx, wasmApp, wasmContract, spec.pinCode) + codeID, _ := setupWasmCode(t, authority, ctx, wasmApp, wasmContract, spec.pinCode) // when msgPruneCodes := &types.MsgPruneWasmCodes{ @@ -921,60 +921,74 @@ func TestPruneWasmCodesAuth(t *testing.T) { func TestPruneWasmCodes(t *testing.T) { specs := map[string]struct { - wasmCode1 []byte - wasmCode2 []byte - pinCode1 bool - pinCode2 bool - expPruned1 bool - expPruned2 bool + wasmCode1 []byte + wasmCode2 []byte + pinCode1 bool + pinCode2 bool + expPrunedCodeInfo1 bool + expPrunedCodeInfo2 bool + expPrunedWasmCode1 bool + expPrunedWasmCode2 bool }{ "duplicate codes - both pinned": { - wasmCode1: wasmContract, - wasmCode2: wasmContract, - pinCode1: true, - pinCode2: true, - expPruned1: false, - expPruned2: false, + wasmCode1: wasmContract, + wasmCode2: wasmContract, + pinCode1: true, + pinCode2: true, + expPrunedCodeInfo1: false, + expPrunedCodeInfo2: false, + expPrunedWasmCode1: false, + expPrunedWasmCode2: false, }, "duplicate codes - only one pinned": { - wasmCode1: wasmContract, - wasmCode2: wasmContract, - pinCode1: true, - pinCode2: false, - expPruned1: false, - expPruned2: true, + wasmCode1: wasmContract, + wasmCode2: wasmContract, + pinCode1: true, + pinCode2: false, + expPrunedCodeInfo1: false, + expPrunedCodeInfo2: true, + expPrunedWasmCode1: false, + expPrunedWasmCode2: false, }, "duplicate codes - both unpinned": { - wasmCode1: wasmContract, - wasmCode2: wasmContract, - pinCode1: false, - pinCode2: false, - expPruned1: true, - expPruned2: true, + wasmCode1: wasmContract, + wasmCode2: wasmContract, + pinCode1: false, + pinCode2: false, + expPrunedCodeInfo1: true, + expPrunedCodeInfo2: true, + expPrunedWasmCode1: true, + expPrunedWasmCode2: true, }, "different codes - both pinned": { - wasmCode1: wasmContract, - wasmCode2: hackatomContract, - pinCode1: true, - pinCode2: true, - expPruned1: false, - expPruned2: false, + wasmCode1: wasmContract, + wasmCode2: hackatomContract, + pinCode1: true, + pinCode2: true, + expPrunedCodeInfo1: false, + expPrunedCodeInfo2: false, + expPrunedWasmCode1: false, + expPrunedWasmCode2: false, }, "different codes - only one pinned": { - wasmCode1: wasmContract, - wasmCode2: hackatomContract, - pinCode1: true, - pinCode2: false, - expPruned1: false, - expPruned2: true, + wasmCode1: wasmContract, + wasmCode2: hackatomContract, + pinCode1: true, + pinCode2: false, + expPrunedCodeInfo1: false, + expPrunedCodeInfo2: true, + expPrunedWasmCode1: false, + expPrunedWasmCode2: true, }, "different codes - both unpinned": { - wasmCode1: wasmContract, - wasmCode2: hackatomContract, - pinCode1: false, - pinCode2: false, - expPruned1: true, - expPruned2: true, + wasmCode1: wasmContract, + wasmCode2: hackatomContract, + pinCode1: false, + pinCode2: false, + expPrunedCodeInfo1: true, + expPrunedCodeInfo2: true, + expPrunedWasmCode1: true, + expPrunedWasmCode2: true, }, } for name, spec := range specs { @@ -983,8 +997,8 @@ func TestPruneWasmCodes(t *testing.T) { ctx := wasmApp.BaseApp.NewContext(false, tmproto.Header{}) authority := wasmApp.WasmKeeper.GetAuthority() - code1 := setupWasmCode(t, authority, ctx, wasmApp, spec.wasmCode1, spec.pinCode1) - code2 := setupWasmCode(t, authority, ctx, wasmApp, spec.wasmCode2, spec.pinCode2) + code1, checksum1 := setupWasmCode(t, authority, ctx, wasmApp, spec.wasmCode1, spec.pinCode1) + code2, checksum2 := setupWasmCode(t, authority, ctx, wasmApp, spec.wasmCode2, spec.pinCode2) // when msgPruneCodes := &types.MsgPruneWasmCodes{ @@ -996,13 +1010,16 @@ func TestPruneWasmCodes(t *testing.T) { // then require.NoError(t, err) - assertPruning(t, ctx, wasmApp, code1, spec.expPruned1) - assertPruning(t, ctx, wasmApp, code2, spec.expPruned2) + assertCodeInfoPruning(t, ctx, wasmApp, code1, spec.expPrunedCodeInfo1) + assertWasmCodePruning(t, ctx, wasmApp, checksum1, spec.expPrunedWasmCode1) + + assertCodeInfoPruning(t, ctx, wasmApp, code2, spec.expPrunedCodeInfo2) + assertWasmCodePruning(t, ctx, wasmApp, checksum2, spec.expPrunedWasmCode2) }) } } -func setupWasmCode(t *testing.T, authority string, ctx sdk.Context, wasmApp *app.WasmApp, wasmCode []byte, pin bool) uint64 { +func setupWasmCode(t *testing.T, authority string, ctx sdk.Context, wasmApp *app.WasmApp, wasmCode []byte, pin bool) (uint64, []byte) { // setup _, _, sender := testdata.KeyTestPubAddr() msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) { @@ -1026,13 +1043,24 @@ func setupWasmCode(t *testing.T, authority string, ctx sdk.Context, wasmApp *app require.NoError(t, err) assert.True(t, wasmApp.WasmKeeper.IsPinnedCode(ctx, result.CodeID)) } - return result.CodeID + return result.CodeID, result.Checksum } -func assertPruning(t *testing.T, ctx sdk.Context, wasmApp *app.WasmApp, codeID uint64, pruned bool) { +func assertCodeInfoPruning(t *testing.T, ctx sdk.Context, wasmApp *app.WasmApp, codeID uint64, pruned bool) { if pruned { assert.Nil(t, wasmApp.WasmKeeper.GetCodeInfo(ctx, codeID)) } else { assert.NotNil(t, wasmApp.WasmKeeper.GetCodeInfo(ctx, codeID)) } } + +func assertWasmCodePruning(t *testing.T, ctx sdk.Context, wasmApp *app.WasmApp, checksum []byte, pruned bool) { + wasmCode, err := wasmApp.WasmKeeper.GetByteCodeByChecksum(ctx, checksum) + if pruned { + assert.Nil(t, wasmCode) + assert.Error(t, err) + } else { + assert.NotNil(t, wasmCode) + assert.NoError(t, err) + } +} From 9ccd0444bad96d81f9ddaeb06f972f162b879d68 Mon Sep 17 00:00:00 2001 From: Pino' Surace Date: Fri, 23 Jun 2023 12:35:15 +0200 Subject: [PATCH 11/18] Rename latestCodeID and add more test cases --- docs/proto/proto-docs.md | 2 +- proto/cosmwasm/wasm/v1/tx.proto | 6 +- x/wasm/client/cli/gov_tx.go | 8 +- x/wasm/keeper/keeper.go | 29 ++- x/wasm/keeper/msg_server.go | 4 +- x/wasm/keeper/msg_server_integration_test.go | 95 ++++++++- x/wasm/types/tx.go | 4 +- x/wasm/types/tx.pb.go | 208 +++++++++---------- x/wasm/types/tx_test.go | 10 +- 9 files changed, 224 insertions(+), 142 deletions(-) diff --git a/docs/proto/proto-docs.md b/docs/proto/proto-docs.md index 911c7532e1..05e6ea0c59 100644 --- a/docs/proto/proto-docs.md +++ b/docs/proto/proto-docs.md @@ -1543,7 +1543,7 @@ MsgPruneWasmCodes is the MsgPruneWasmCodes request type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | `authority` | [string](#string) | | Authority is the address of the governance account. | -| `latest_code_id` | [uint64](#uint64) | | LatestCodeID is the upper limit so that all unpinned code ids code ids <= than latestCodeID will be pruned | +| `max_code_id` | [uint64](#uint64) | | MaxCodeID is the upper limit so that all unpinned code ids code ids <= than maxCodeID will be pruned | diff --git a/proto/cosmwasm/wasm/v1/tx.proto b/proto/cosmwasm/wasm/v1/tx.proto index b9ecbacb42..5a067e6ab3 100644 --- a/proto/cosmwasm/wasm/v1/tx.proto +++ b/proto/cosmwasm/wasm/v1/tx.proto @@ -400,9 +400,9 @@ message MsgPruneWasmCodes { // Authority is the address of the governance account. string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; - // LatestCodeID is the upper limit so that all unpinned code ids - // code ids <= than latestCodeID will be pruned - uint64 latest_code_id = 2 [ (gogoproto.customname) = "LatestCodeID" ]; + // MaxCodeID is the upper limit so that all unpinned code ids + // code ids <= than maxCodeID will be pruned + uint64 max_code_id = 2 [ (gogoproto.customname) = "MaxCodeID" ]; } // MsgPruneWasmCodesResponse defines the response structure for executing a diff --git a/x/wasm/client/cli/gov_tx.go b/x/wasm/client/cli/gov_tx.go index fa11ad938c..50d64bfd5b 100644 --- a/x/wasm/client/cli/gov_tx.go +++ b/x/wasm/client/cli/gov_tx.go @@ -804,8 +804,8 @@ $ %s tx gov submit-proposal update-instantiate-config 1:nobody 2:everybody 3:%s1 func ProposalPruneWasmCodesCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "prune-wasm-codes [latest-code-id] --title [text] --summary [text] --authority [address]", - Short: "Submit a prune wasm codes proposal for pruning unpinned wasm codes smaller than latest-code-id", + Use: "prune-wasm-codes [max-code-id] --title [text] --summary [text] --authority [address]", + Short: "Submit a prune wasm codes proposal for pruning unpinned wasm codes smaller than max-code-id", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { clientCtx, proposalTitle, summary, deposit, err := getProposalInfo(cmd) @@ -827,8 +827,8 @@ func ProposalPruneWasmCodesCmd() *cobra.Command { } msg := types.MsgPruneWasmCodes{ - Authority: authority, - LatestCodeID: codeID, + Authority: authority, + MaxCodeID: codeID, } proposalMsg, err := v1.NewMsgSubmitProposal([]sdk.Msg{&msg}, deposit, clientCtx.GetFromAddress().String(), "", proposalTitle, summary) diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index 5a1d599cf3..2b81d13ee9 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -1238,10 +1238,10 @@ func (k Keeper) iteratePinnedCodes(ctx sdk.Context, cb func(codeID uint64) bool) } } -// PruneWasmCodes deletes code info for unpinned codes <= than latestCodeID -func (k Keeper) PruneWasmCodes(ctx sdk.Context, latestCodeID uint64) error { - usedCodeIds := make(map[uint64]struct{}, 0) - usedChecksums := make(map[string]bool, 0) +// PruneWasmCodes deletes code info for unpinned codes <= than maxCodeID +func (k Keeper) PruneWasmCodes(ctx sdk.Context, maxCodeID uint64) error { + usedCodeIds := make(map[uint64]struct{}) + usedChecksums := make(map[string]bool) // collect code ids used by contracts k.IterateContractInfo(ctx, func(_ sdk.AccAddress, info types.ContractInfo) bool { @@ -1255,10 +1255,10 @@ func (k Keeper) PruneWasmCodes(ctx sdk.Context, latestCodeID uint64) error { return false }) - // check if instances are used only by unpinned code ids <= latestCodeID + // check if instances are used only by unpinned code ids <= maxCodeID k.IterateCodeInfos(ctx, func(codeID uint64, info types.CodeInfo) bool { - if _, ok := usedCodeIds[codeID]; !ok && codeID <= latestCodeID { - if _, found := usedChecksums[string(info.CodeHash)]; !found { + if _, ok := usedCodeIds[codeID]; !ok && codeID <= maxCodeID { + if !usedChecksums[string(info.CodeHash)] { usedChecksums[string(info.CodeHash)] = false } return false @@ -1267,19 +1267,28 @@ func (k Keeper) PruneWasmCodes(ctx sdk.Context, latestCodeID uint64) error { return false }) - // delete all unpinned code ids <= latestCodeID and all the - // instances used only by unpinned code ids <= latestCodeID + var ( + deletedCodeInfoCounter int + deletedWasmFileCounter int + ) + // delete all unpinned code ids <= maxCodeID and all the + // instances used only by unpinned code ids <= maxCodeID k.IterateCodeInfos(ctx, func(codeID uint64, info types.CodeInfo) bool { - if _, ok := usedCodeIds[codeID]; !ok && codeID <= latestCodeID { + if _, ok := usedCodeIds[codeID]; !ok && codeID <= maxCodeID { k.deleteCodeInfo(ctx, codeID) + deletedCodeInfoCounter++ if !usedChecksums[string(info.CodeHash)] { if err := k.wasmVM.RemoveCode(info.CodeHash); err != nil { k.Logger(ctx).Error("failed to delete wasm file on disk", "checksum", info.CodeHash) + } else { + deletedWasmFileCounter++ } } } return false }) + k.Logger(ctx).Info("deleted unused wasm files", "total", deletedWasmFileCounter) + k.Logger(ctx).Info("deleted unused code infos", "total", deletedCodeInfoCounter) return nil } diff --git a/x/wasm/keeper/msg_server.go b/x/wasm/keeper/msg_server.go index a586df8986..5ceca2370d 100644 --- a/x/wasm/keeper/msg_server.go +++ b/x/wasm/keeper/msg_server.go @@ -364,7 +364,7 @@ func (m msgServer) selectAuthorizationPolicy(actor string) AuthorizationPolicy { return DefaultAuthorizationPolicy{} } -// PruneWasmCodes prunes unpinned code ids smaller than given code id. +// PruneWasmCodes prunes unpinned code ids smaller than max code id. func (m msgServer) PruneWasmCodes(goCtx context.Context, req *types.MsgPruneWasmCodes) (*types.MsgPruneWasmCodesResponse, error) { if err := req.ValidateBasic(); err != nil { return nil, err @@ -375,7 +375,7 @@ func (m msgServer) PruneWasmCodes(goCtx context.Context, req *types.MsgPruneWasm } ctx := sdk.UnwrapSDKContext(goCtx) - err := m.keeper.PruneWasmCodes(ctx, req.LatestCodeID) + err := m.keeper.PruneWasmCodes(ctx, req.MaxCodeID) if err != nil { return nil, err } diff --git a/x/wasm/keeper/msg_server_integration_test.go b/x/wasm/keeper/msg_server_integration_test.go index 1bb9327fa4..8741d8c5fa 100644 --- a/x/wasm/keeper/msg_server_integration_test.go +++ b/x/wasm/keeper/msg_server_integration_test.go @@ -854,7 +854,7 @@ func TestUpdateInstantiateConfig(t *testing.T) { } } -func TestPruneWasmCodesAuth(t *testing.T) { +func TestPruneWasmCodesAuthority(t *testing.T) { wasmApp := app.Setup(t) ctx := wasmApp.BaseApp.NewContext(false, tmproto.Header{}) @@ -898,8 +898,8 @@ func TestPruneWasmCodesAuth(t *testing.T) { // when msgPruneCodes := &types.MsgPruneWasmCodes{ - Authority: spec.addr, - LatestCodeID: 5, + Authority: spec.addr, + MaxCodeID: 5, } _, err := wasmApp.MsgServiceRouter().Handler(msgPruneCodes)(ctx, msgPruneCodes) @@ -929,8 +929,9 @@ func TestPruneWasmCodes(t *testing.T) { expPrunedCodeInfo2 bool expPrunedWasmCode1 bool expPrunedWasmCode2 bool + maxCodeID uint64 }{ - "duplicate codes - both pinned": { + "duplicate codes - both pinned - max code id 2": { wasmCode1: wasmContract, wasmCode2: wasmContract, pinCode1: true, @@ -939,8 +940,9 @@ func TestPruneWasmCodes(t *testing.T) { expPrunedCodeInfo2: false, expPrunedWasmCode1: false, expPrunedWasmCode2: false, + maxCodeID: 2, }, - "duplicate codes - only one pinned": { + "duplicate codes - only one pinned - max code id 2": { wasmCode1: wasmContract, wasmCode2: wasmContract, pinCode1: true, @@ -949,8 +951,9 @@ func TestPruneWasmCodes(t *testing.T) { expPrunedCodeInfo2: true, expPrunedWasmCode1: false, expPrunedWasmCode2: false, + maxCodeID: 2, }, - "duplicate codes - both unpinned": { + "duplicate codes - both unpinned - max code id 2": { wasmCode1: wasmContract, wasmCode2: wasmContract, pinCode1: false, @@ -959,8 +962,9 @@ func TestPruneWasmCodes(t *testing.T) { expPrunedCodeInfo2: true, expPrunedWasmCode1: true, expPrunedWasmCode2: true, + maxCodeID: 2, }, - "different codes - both pinned": { + "different codes - both pinned - max code id 2": { wasmCode1: wasmContract, wasmCode2: hackatomContract, pinCode1: true, @@ -969,8 +973,9 @@ func TestPruneWasmCodes(t *testing.T) { expPrunedCodeInfo2: false, expPrunedWasmCode1: false, expPrunedWasmCode2: false, + maxCodeID: 2, }, - "different codes - only one pinned": { + "different codes - only one pinned - max code id 2": { wasmCode1: wasmContract, wasmCode2: hackatomContract, pinCode1: true, @@ -979,8 +984,9 @@ func TestPruneWasmCodes(t *testing.T) { expPrunedCodeInfo2: true, expPrunedWasmCode1: false, expPrunedWasmCode2: true, + maxCodeID: 2, }, - "different codes - both unpinned": { + "different codes - both unpinned - max code id 2": { wasmCode1: wasmContract, wasmCode2: hackatomContract, pinCode1: false, @@ -989,6 +995,73 @@ func TestPruneWasmCodes(t *testing.T) { expPrunedCodeInfo2: true, expPrunedWasmCode1: true, expPrunedWasmCode2: true, + maxCodeID: 2, + }, + "duplicate codes - both pinned - max code id 1": { + wasmCode1: wasmContract, + wasmCode2: wasmContract, + pinCode1: true, + pinCode2: true, + expPrunedCodeInfo1: false, + expPrunedCodeInfo2: false, + expPrunedWasmCode1: false, + expPrunedWasmCode2: false, + maxCodeID: 1, + }, + "duplicate codes - only one pinned - max code id 1": { + wasmCode1: wasmContract, + wasmCode2: wasmContract, + pinCode1: true, + pinCode2: false, + expPrunedCodeInfo1: false, + expPrunedCodeInfo2: false, + expPrunedWasmCode1: false, + expPrunedWasmCode2: false, + maxCodeID: 1, + }, + "duplicate codes - both unpinned - max code id 1": { + wasmCode1: wasmContract, + wasmCode2: wasmContract, + pinCode1: false, + pinCode2: false, + expPrunedCodeInfo1: true, + expPrunedCodeInfo2: false, + expPrunedWasmCode1: false, + expPrunedWasmCode2: false, + maxCodeID: 1, + }, + "different codes - both pinned - max code id 1": { + wasmCode1: wasmContract, + wasmCode2: hackatomContract, + pinCode1: true, + pinCode2: true, + expPrunedCodeInfo1: false, + expPrunedCodeInfo2: false, + expPrunedWasmCode1: false, + expPrunedWasmCode2: false, + maxCodeID: 1, + }, + "different codes - only one pinned - max code id 1": { + wasmCode1: wasmContract, + wasmCode2: hackatomContract, + pinCode1: true, + pinCode2: false, + expPrunedCodeInfo1: false, + expPrunedCodeInfo2: false, + expPrunedWasmCode1: false, + expPrunedWasmCode2: false, + maxCodeID: 1, + }, + "different codes - both unpinned - max code id 1": { + wasmCode1: wasmContract, + wasmCode2: hackatomContract, + pinCode1: false, + pinCode2: false, + expPrunedCodeInfo1: true, + expPrunedCodeInfo2: false, + expPrunedWasmCode1: true, + expPrunedWasmCode2: false, + maxCodeID: 1, }, } for name, spec := range specs { @@ -1002,8 +1075,8 @@ func TestPruneWasmCodes(t *testing.T) { // when msgPruneCodes := &types.MsgPruneWasmCodes{ - Authority: authority, - LatestCodeID: 5, + Authority: authority, + MaxCodeID: spec.maxCodeID, } _, err := wasmApp.MsgServiceRouter().Handler(msgPruneCodes)(ctx, msgPruneCodes) diff --git a/x/wasm/types/tx.go b/x/wasm/types/tx.go index 9f1a9e1a86..ae2140d93e 100644 --- a/x/wasm/types/tx.go +++ b/x/wasm/types/tx.go @@ -640,8 +640,8 @@ func (msg MsgPruneWasmCodes) ValidateBasic() error { if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil { return errorsmod.Wrap(err, "authority") } - if msg.LatestCodeID == 0 { - return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "latest code id is required") + if msg.MaxCodeID == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "max code id is required") } return nil } diff --git a/x/wasm/types/tx.pb.go b/x/wasm/types/tx.pb.go index 62a19a70ed..6c76ce0598 100644 --- a/x/wasm/types/tx.pb.go +++ b/x/wasm/types/tx.pb.go @@ -1293,9 +1293,9 @@ var xxx_messageInfo_MsgStoreAndInstantiateContractResponse proto.InternalMessage type MsgPruneWasmCodes struct { // Authority is the address of the governance account. Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` - // LatestCodeID is the upper limit so that all unpinned code ids - // code ids <= than latestCodeID will be pruned - LatestCodeID uint64 `protobuf:"varint,2,opt,name=latest_code_id,json=latestCodeId,proto3" json:"latest_code_id,omitempty"` + // MaxCodeID is the upper limit so that all unpinned code ids + // code ids <= than maxCodeID will be pruned + MaxCodeID uint64 `protobuf:"varint,2,opt,name=max_code_id,json=maxCodeId,proto3" json:"max_code_id,omitempty"` } func (m *MsgPruneWasmCodes) Reset() { *m = MsgPruneWasmCodes{} } @@ -1414,100 +1414,100 @@ func init() { proto.RegisterFile("cosmwasm/wasm/v1/tx.proto", fileDescriptor_4f7 var fileDescriptor_4f74d82755520264 = []byte{ // 1513 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x58, 0xcd, 0x6f, 0x1b, 0x45, - 0x14, 0xcf, 0xc6, 0xdf, 0xcf, 0x26, 0x4d, 0xb7, 0x6e, 0xe2, 0x6c, 0x5a, 0x3b, 0xdd, 0xf4, 0xc3, - 0xfd, 0xb2, 0x1b, 0x03, 0x11, 0x98, 0x53, 0x9c, 0x22, 0x91, 0x0a, 0x43, 0xe4, 0xa8, 0x8d, 0x40, - 0x95, 0xac, 0xb5, 0x77, 0xb2, 0x59, 0xd5, 0xbb, 0x6b, 0x76, 0xd6, 0x4d, 0x72, 0xe0, 0x02, 0x12, - 0x12, 0x9c, 0xb8, 0xf2, 0x07, 0x20, 0x01, 0x07, 0xe8, 0x81, 0x03, 0xc7, 0x1e, 0x2b, 0x71, 0xa9, - 0x38, 0x71, 0x0a, 0x90, 0x22, 0x95, 0x1b, 0x12, 0x47, 0x4e, 0x68, 0x66, 0x76, 0xd7, 0xeb, 0xf5, - 0xae, 0xe3, 0x24, 0x54, 0x1c, 0xb8, 0x24, 0x3b, 0xf3, 0x3e, 0xe6, 0xfd, 0x7e, 0xef, 0xcd, 0xcc, - 0x1b, 0xc3, 0x5c, 0xdb, 0xc0, 0xda, 0x8e, 0x84, 0xb5, 0x32, 0xfd, 0xf3, 0x70, 0xa9, 0x6c, 0xed, - 0x96, 0xba, 0xa6, 0x61, 0x19, 0xfc, 0xb4, 0x23, 0x2a, 0xd1, 0x3f, 0x0f, 0x97, 0x84, 0x3c, 0x99, - 0x31, 0x70, 0xb9, 0x25, 0x61, 0x54, 0x7e, 0xb8, 0xd4, 0x42, 0x96, 0xb4, 0x54, 0x6e, 0x1b, 0xaa, - 0xce, 0x2c, 0x84, 0x59, 0x5b, 0xae, 0x61, 0x85, 0x78, 0xd2, 0xb0, 0x62, 0x0b, 0xb2, 0x8a, 0xa1, - 0x18, 0xf4, 0xb3, 0x4c, 0xbe, 0xec, 0xd9, 0x73, 0xc3, 0x6b, 0xef, 0x75, 0x11, 0xb6, 0xa5, 0x73, - 0xcc, 0x59, 0x93, 0x99, 0xb1, 0x81, 0x2d, 0x3a, 0x2d, 0x69, 0xaa, 0x6e, 0x94, 0xe9, 0x5f, 0x36, - 0x25, 0xfe, 0xce, 0x41, 0xa6, 0x8e, 0x95, 0x0d, 0xcb, 0x30, 0xd1, 0xaa, 0x21, 0x23, 0x7e, 0x06, - 0xe2, 0x18, 0xe9, 0x32, 0x32, 0x73, 0xdc, 0x02, 0x57, 0x4c, 0x35, 0xec, 0x11, 0xbf, 0x0c, 0x53, - 0x64, 0xb5, 0x66, 0x6b, 0xcf, 0x42, 0xcd, 0xb6, 0x21, 0xa3, 0xdc, 0xe4, 0x02, 0x57, 0xcc, 0xd4, - 0xa6, 0x0f, 0xf6, 0x0b, 0x99, 0xcd, 0x95, 0x8d, 0x7a, 0x6d, 0xcf, 0xa2, 0x1e, 0x1a, 0x19, 0xa2, - 0xe7, 0x8c, 0xf8, 0xbb, 0x30, 0xa3, 0xea, 0xd8, 0x92, 0x74, 0x4b, 0x95, 0x2c, 0xd4, 0xec, 0x22, - 0x53, 0x53, 0x31, 0x56, 0x0d, 0x3d, 0x17, 0x5b, 0xe0, 0x8a, 0xe9, 0x4a, 0xbe, 0xe4, 0xa7, 0xab, - 0xb4, 0xd2, 0x6e, 0x23, 0x8c, 0x57, 0x0d, 0x7d, 0x4b, 0x55, 0x1a, 0x67, 0x3d, 0xd6, 0xeb, 0xae, - 0x71, 0xf5, 0xc2, 0x47, 0xcf, 0x1f, 0x5d, 0xb3, 0x63, 0xfb, 0xec, 0xf9, 0xa3, 0x6b, 0xa7, 0x29, - 0x15, 0x5e, 0x24, 0x77, 0xa2, 0xc9, 0xc8, 0x74, 0xf4, 0x4e, 0x34, 0x19, 0x9d, 0x8e, 0x89, 0x9b, - 0x90, 0xf5, 0xca, 0x1a, 0x08, 0x77, 0x0d, 0x1d, 0x23, 0x7e, 0x11, 0x12, 0x04, 0x4b, 0x53, 0x95, - 0x29, 0xdc, 0x68, 0x0d, 0x0e, 0xf6, 0x0b, 0x71, 0xa2, 0xb2, 0x76, 0xbb, 0x11, 0x27, 0xa2, 0x35, - 0x99, 0x17, 0x20, 0xd9, 0xde, 0x46, 0xed, 0x07, 0xb8, 0xa7, 0x31, 0xd0, 0x0d, 0x77, 0x2c, 0x3e, - 0x9e, 0x84, 0x99, 0x3a, 0x56, 0xd6, 0xfa, 0x41, 0xae, 0x1a, 0xba, 0x65, 0x4a, 0x6d, 0x2b, 0x94, - 0xc9, 0x2c, 0xc4, 0x24, 0x59, 0x53, 0x75, 0xea, 0x2b, 0xd5, 0x60, 0x03, 0x6f, 0x24, 0x91, 0xd0, - 0x48, 0xb2, 0x10, 0xeb, 0x48, 0x2d, 0xd4, 0xc9, 0x45, 0x99, 0x29, 0x1d, 0xf0, 0x45, 0x88, 0x68, - 0x58, 0xa1, 0x7c, 0x66, 0x6a, 0x33, 0x7f, 0xef, 0x17, 0xf8, 0x86, 0xb4, 0xe3, 0x84, 0x51, 0x47, - 0x18, 0x4b, 0x0a, 0x6a, 0x10, 0x15, 0x7e, 0x0b, 0x62, 0x5b, 0x3d, 0x5d, 0xc6, 0xb9, 0xf8, 0x42, - 0xa4, 0x98, 0xae, 0xcc, 0x95, 0xec, 0xf2, 0x20, 0x85, 0x59, 0xb2, 0x0b, 0xb3, 0xb4, 0x6a, 0xa8, - 0x7a, 0xed, 0xd5, 0x27, 0xfb, 0x85, 0x89, 0x6f, 0x7e, 0x29, 0x14, 0x15, 0xd5, 0xda, 0xee, 0xb5, - 0x4a, 0x6d, 0x43, 0xb3, 0x6b, 0xc9, 0xfe, 0x77, 0x13, 0xcb, 0x0f, 0xec, 0xba, 0x23, 0x06, 0xf8, - 0xab, 0xe7, 0x8f, 0xae, 0x71, 0x0d, 0xe6, 0xbe, 0x7a, 0xdd, 0x97, 0x9d, 0x79, 0x27, 0x3b, 0x01, - 0x3c, 0x89, 0xef, 0x40, 0x3e, 0x58, 0xe2, 0x66, 0x29, 0x07, 0x09, 0x49, 0x96, 0x4d, 0x84, 0xb1, - 0x4d, 0xa5, 0x33, 0xe4, 0x79, 0x88, 0xca, 0x92, 0x25, 0xd9, 0x69, 0xa1, 0xdf, 0xe2, 0x9f, 0x93, - 0x30, 0x1b, 0xec, 0xb0, 0xf2, 0x3f, 0xce, 0x09, 0xa1, 0x0a, 0x4b, 0x1d, 0x2b, 0x97, 0x60, 0x54, - 0x91, 0x6f, 0x7e, 0x16, 0x12, 0x5b, 0xea, 0x6e, 0x93, 0x44, 0x9a, 0x5c, 0xe0, 0x8a, 0xc9, 0x46, - 0x7c, 0x4b, 0xdd, 0xad, 0x63, 0xa5, 0x7a, 0xc3, 0x97, 0xc0, 0x73, 0x23, 0x12, 0x58, 0x11, 0xdf, - 0x85, 0x42, 0x88, 0xe8, 0x98, 0x29, 0xfc, 0x78, 0x12, 0xf8, 0x3a, 0x56, 0xde, 0xdc, 0x45, 0xed, - 0xde, 0x18, 0x3b, 0x8a, 0x6c, 0x50, 0x5b, 0xc7, 0x4e, 0xa0, 0x3b, 0x76, 0x12, 0x11, 0x39, 0x42, - 0x22, 0x62, 0x2f, 0x76, 0x73, 0x5c, 0xf1, 0x71, 0x3b, 0xeb, 0x70, 0xeb, 0x83, 0x2b, 0xde, 0x02, - 0x61, 0x78, 0xd6, 0x65, 0xd4, 0xe1, 0x8d, 0xf3, 0xf0, 0xf6, 0x98, 0xa3, 0xbc, 0xd5, 0x55, 0xc5, - 0x94, 0x4e, 0xc8, 0xdb, 0x58, 0xb5, 0x6f, 0x93, 0x1b, 0x3d, 0x94, 0xdc, 0x70, 0xd0, 0xbe, 0x58, - 0x6d, 0xd0, 0xbe, 0xd9, 0x91, 0xa0, 0x3f, 0xe1, 0x60, 0xaa, 0x8e, 0x95, 0xbb, 0x5d, 0x59, 0xb2, - 0xd0, 0x0a, 0xdd, 0xb8, 0x61, 0x80, 0xe7, 0x21, 0xa5, 0xa3, 0x9d, 0xa6, 0x77, 0xab, 0x27, 0x75, - 0xb4, 0xc3, 0x8c, 0xbc, 0x6c, 0x44, 0x06, 0xd9, 0xa8, 0x2e, 0xfa, 0xc2, 0x3f, 0xe3, 0x84, 0xef, - 0x59, 0x55, 0xcc, 0xd1, 0xab, 0xc0, 0x33, 0xe3, 0x84, 0x2d, 0x2a, 0xf0, 0x52, 0x1d, 0x2b, 0xab, - 0x1d, 0x24, 0x99, 0xa3, 0x03, 0x1c, 0x15, 0x83, 0xe8, 0x8b, 0x81, 0x77, 0x62, 0xe8, 0xfb, 0x15, - 0x67, 0xe1, 0xec, 0xc0, 0x84, 0x1b, 0xc1, 0x1f, 0x1c, 0xe5, 0x95, 0x05, 0x37, 0xb8, 0x53, 0xb7, - 0x54, 0x25, 0x34, 0x1e, 0x4f, 0x15, 0x4c, 0x86, 0x56, 0xc1, 0x7d, 0x10, 0x08, 0xab, 0x21, 0xd7, - 0x7c, 0x64, 0xac, 0x6b, 0x3e, 0xa7, 0xa3, 0x9d, 0xb5, 0xc0, 0x9b, 0xbe, 0xec, 0x83, 0x5d, 0x18, - 0xa4, 0x7e, 0x08, 0x8b, 0x78, 0x11, 0xc4, 0x70, 0xa9, 0x4b, 0xc8, 0x77, 0x1c, 0x9c, 0x72, 0xd5, - 0xd6, 0x25, 0x53, 0xd2, 0x30, 0xbf, 0x0c, 0x29, 0xa9, 0x67, 0x6d, 0x1b, 0xa6, 0x6a, 0xed, 0x31, - 0x22, 0x6a, 0xb9, 0x9f, 0xbe, 0xbf, 0x99, 0xb5, 0x0f, 0x82, 0x15, 0x76, 0x62, 0x6d, 0x58, 0xa6, - 0xaa, 0x2b, 0x8d, 0xbe, 0x2a, 0xff, 0x06, 0xc4, 0xbb, 0xd4, 0x03, 0x25, 0x29, 0x5d, 0xc9, 0x0d, - 0x83, 0x65, 0x2b, 0xd4, 0x52, 0xe4, 0xe4, 0x60, 0xa7, 0x81, 0x6d, 0xc2, 0x76, 0x46, 0xdf, 0x19, - 0x81, 0x98, 0x1d, 0x84, 0xc8, 0x6c, 0xc5, 0x39, 0x7a, 0xad, 0x79, 0xa7, 0x5c, 0x30, 0x3f, 0x30, - 0x30, 0x1b, 0x3d, 0xd9, 0x70, 0x37, 0xfd, 0x71, 0xc1, 0xfc, 0x2b, 0x87, 0xe9, 0x48, 0x54, 0xde, - 0x30, 0xc5, 0x9b, 0x14, 0x95, 0x77, 0x6a, 0xe4, 0x66, 0xff, 0x92, 0x83, 0x74, 0x1d, 0x2b, 0xeb, - 0xaa, 0x4e, 0x8a, 0xf0, 0xf8, 0x29, 0x7b, 0x9d, 0xa0, 0xa4, 0x85, 0x4d, 0x92, 0x16, 0x29, 0x46, - 0x6b, 0xf9, 0x83, 0xfd, 0x42, 0x82, 0x55, 0x36, 0xfe, 0x6b, 0xbf, 0x70, 0x6a, 0x4f, 0xd2, 0x3a, - 0x55, 0xd1, 0x51, 0x12, 0x1b, 0x09, 0x56, 0xed, 0x98, 0x9d, 0x05, 0x83, 0xd0, 0xa6, 0x1d, 0x68, - 0x4e, 0x5c, 0xe2, 0x59, 0x38, 0xe3, 0x19, 0xba, 0x89, 0xfa, 0x9a, 0xa3, 0x27, 0xc1, 0x5d, 0xbd, - 0xfb, 0x1f, 0x02, 0xb8, 0x34, 0x0c, 0xc0, 0x3d, 0x4b, 0xfa, 0x91, 0xd9, 0x67, 0x49, 0x7f, 0xc2, - 0x05, 0xf1, 0x63, 0x94, 0x76, 0x6c, 0xb4, 0x9b, 0x5e, 0xd1, 0xe5, 0xa0, 0xde, 0xf7, 0xb8, 0xa8, - 0x86, 0x5f, 0x19, 0x91, 0x13, 0xbe, 0x32, 0xa2, 0x27, 0x78, 0x65, 0xf0, 0xe7, 0x01, 0x7a, 0x04, - 0x3f, 0x0b, 0x25, 0x46, 0x5b, 0xa4, 0x54, 0xcf, 0x61, 0xa4, 0xdf, 0x35, 0xc6, 0xbd, 0x5d, 0xa3, - 0xdb, 0x10, 0x26, 0x02, 0x1a, 0xc2, 0xe4, 0x11, 0xfa, 0x90, 0xd4, 0x8b, 0x6d, 0x08, 0xc9, 0x99, - 0x6f, 0xf4, 0xcc, 0x36, 0xca, 0x81, 0x7d, 0xe6, 0xd3, 0x11, 0x69, 0xd5, 0x5a, 0x3d, 0xb5, 0x43, - 0x2e, 0x83, 0x34, 0x6b, 0xd5, 0xec, 0x21, 0xb9, 0x3e, 0x69, 0x39, 0x6d, 0x4b, 0x78, 0x3b, 0x97, - 0xb1, 0x5f, 0x42, 0x86, 0x8c, 0xde, 0x92, 0xf0, 0x76, 0x75, 0x79, 0xb8, 0xaa, 0x16, 0x07, 0x1e, - 0x65, 0xc1, 0xa5, 0x22, 0xde, 0x83, 0xcb, 0xa3, 0x35, 0x8e, 0xd9, 0x43, 0x7e, 0xcb, 0xc1, 0x69, - 0xb2, 0x05, 0xcd, 0x9e, 0x8e, 0x36, 0x25, 0xac, 0x9d, 0x6c, 0xbb, 0x2d, 0xc3, 0x54, 0x47, 0xb2, - 0x10, 0xb6, 0x9a, 0x83, 0xf7, 0x21, 0x2d, 0xcc, 0xb7, 0xa9, 0xc4, 0xbe, 0x15, 0x33, 0x9d, 0xfe, - 0x48, 0xae, 0x5e, 0x1d, 0x66, 0x65, 0xc6, 0x3d, 0x2c, 0x06, 0x42, 0x13, 0xe7, 0x61, 0x6e, 0x68, - 0xd2, 0xc1, 0x5e, 0xf9, 0x22, 0x0d, 0x91, 0x3a, 0x56, 0xf8, 0x0d, 0x48, 0xf5, 0xdf, 0xea, 0x01, - 0x55, 0xed, 0x7d, 0xe5, 0x0a, 0x97, 0x47, 0xcb, 0x5d, 0x62, 0x3f, 0x80, 0x33, 0x41, 0x9b, 0xb8, - 0x18, 0x68, 0x1e, 0xa0, 0x29, 0xdc, 0x1a, 0x57, 0xd3, 0x5d, 0xd2, 0x82, 0x6c, 0xe0, 0x03, 0xed, - 0xea, 0xb8, 0x9e, 0x2a, 0xc2, 0xd2, 0xd8, 0xaa, 0xee, 0xaa, 0x08, 0x4e, 0xf9, 0xdf, 0x14, 0x17, - 0x03, 0xbd, 0xf8, 0xb4, 0x84, 0x1b, 0xe3, 0x68, 0x79, 0x97, 0xf1, 0xb7, 0xe0, 0xc1, 0xcb, 0xf8, - 0xb4, 0x42, 0x96, 0x09, 0x6b, 0x86, 0xdf, 0x83, 0xb4, 0xb7, 0xe9, 0x5d, 0x08, 0x34, 0xf6, 0x68, - 0x08, 0xc5, 0xc3, 0x34, 0x5c, 0xd7, 0xf7, 0x00, 0x3c, 0xdd, 0x6a, 0x21, 0xd0, 0xae, 0xaf, 0x20, - 0x5c, 0x39, 0x44, 0xc1, 0xf5, 0xfb, 0x21, 0xcc, 0x86, 0xb5, 0xa0, 0x37, 0x46, 0x04, 0x37, 0xa4, - 0x2d, 0xbc, 0x72, 0x14, 0x6d, 0x77, 0xf9, 0xfb, 0x90, 0x19, 0x68, 0xf8, 0x2e, 0x8c, 0xf0, 0xc2, - 0x54, 0x84, 0xab, 0x87, 0xaa, 0x78, 0xbd, 0x0f, 0x74, 0x60, 0xc1, 0xde, 0xbd, 0x2a, 0x21, 0xde, - 0x03, 0xbb, 0xa1, 0x75, 0x48, 0xba, 0x5d, 0xcf, 0xf9, 0x40, 0x33, 0x47, 0x2c, 0x5c, 0x1a, 0x29, - 0xf6, 0x26, 0xd9, 0xd3, 0x88, 0x04, 0x27, 0xb9, 0xaf, 0x10, 0x92, 0xe4, 0xe1, 0xfe, 0x80, 0xff, - 0x94, 0x83, 0xf9, 0x51, 0xcd, 0xc1, 0xad, 0xf0, 0x63, 0x29, 0xd8, 0x42, 0x78, 0xed, 0xa8, 0x16, - 0x6e, 0x2c, 0x2d, 0x98, 0xf2, 0xdd, 0x00, 0x8b, 0xc1, 0xe4, 0x0c, 0x28, 0x09, 0xd7, 0xc7, 0x50, - 0x72, 0xd6, 0xa8, 0xdd, 0x7e, 0xf2, 0x5b, 0x7e, 0xe2, 0xc9, 0x41, 0x9e, 0x7b, 0x7a, 0x90, 0xe7, - 0x7e, 0x3d, 0xc8, 0x73, 0x9f, 0x3f, 0xcb, 0x4f, 0x3c, 0x7d, 0x96, 0x9f, 0xf8, 0xf9, 0x59, 0x7e, - 0xe2, 0xfd, 0xcb, 0x9e, 0xcb, 0x79, 0xd5, 0xc0, 0xda, 0xa6, 0xf3, 0xc3, 0xad, 0x5c, 0xde, 0x65, - 0x3f, 0xe0, 0xd2, 0x0b, 0xba, 0x15, 0xa7, 0x3f, 0xc8, 0xbe, 0xfc, 0x4f, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xf4, 0x27, 0xa9, 0xed, 0x5a, 0x16, 0x00, 0x00, + 0x14, 0xcf, 0xc6, 0xdf, 0xcf, 0x6e, 0x9b, 0x6e, 0xdd, 0xc4, 0xd9, 0xb4, 0x76, 0xba, 0xe9, 0x87, + 0xfb, 0x11, 0xbb, 0x31, 0x50, 0x81, 0x39, 0xc5, 0x29, 0x12, 0xa9, 0x64, 0x88, 0x1c, 0xb5, 0x11, + 0xa8, 0x92, 0x35, 0xf6, 0x4e, 0x36, 0xab, 0x66, 0x77, 0x8d, 0x67, 0xdd, 0x38, 0x07, 0x2e, 0x20, + 0x21, 0xc1, 0x89, 0x2b, 0x7f, 0x40, 0x25, 0xe0, 0x42, 0x0f, 0x1c, 0x38, 0xf6, 0x58, 0x89, 0x4b, + 0xc5, 0x89, 0x93, 0x01, 0x17, 0x29, 0xdc, 0x90, 0x38, 0x72, 0x42, 0x33, 0xfb, 0xe1, 0xf5, 0x7a, + 0xd7, 0x71, 0x12, 0x2a, 0x0e, 0x5c, 0x92, 0x9d, 0x99, 0xf7, 0xde, 0xbc, 0xdf, 0xef, 0xbd, 0x79, + 0xf3, 0xc6, 0x30, 0xdf, 0xd4, 0x89, 0xba, 0x87, 0x88, 0x5a, 0x64, 0x7f, 0x1e, 0xaf, 0x14, 0x8d, + 0x6e, 0xa1, 0xd5, 0xd6, 0x0d, 0x9d, 0x9f, 0xb1, 0x97, 0x0a, 0xec, 0xcf, 0xe3, 0x15, 0x21, 0x4b, + 0x67, 0x74, 0x52, 0x6c, 0x20, 0x82, 0x8b, 0x8f, 0x57, 0x1a, 0xd8, 0x40, 0x2b, 0xc5, 0xa6, 0xae, + 0x68, 0xa6, 0x86, 0x30, 0x67, 0xad, 0xab, 0x44, 0xa6, 0x96, 0x54, 0x22, 0x5b, 0x0b, 0x69, 0x59, + 0x97, 0x75, 0xf6, 0x59, 0xa4, 0x5f, 0xd6, 0xec, 0x85, 0xd1, 0xbd, 0xf7, 0x5b, 0x98, 0x58, 0xab, + 0xf3, 0xa6, 0xb1, 0xba, 0xa9, 0x66, 0x0e, 0xac, 0xa5, 0xb3, 0x48, 0x55, 0x34, 0xbd, 0xc8, 0xfe, + 0x9a, 0x53, 0xe2, 0xef, 0x1c, 0xa4, 0xaa, 0x44, 0xde, 0x34, 0xf4, 0x36, 0x5e, 0xd3, 0x25, 0xcc, + 0xcf, 0x42, 0x94, 0x60, 0x4d, 0xc2, 0xed, 0x0c, 0xb7, 0xc8, 0xe5, 0x13, 0x35, 0x6b, 0xc4, 0xdf, + 0x81, 0xd3, 0x74, 0xb7, 0x7a, 0x63, 0xdf, 0xc0, 0xf5, 0xa6, 0x2e, 0xe1, 0xcc, 0xf4, 0x22, 0x97, + 0x4f, 0x55, 0x66, 0xfa, 0xbd, 0x5c, 0x6a, 0x6b, 0x75, 0xb3, 0x5a, 0xd9, 0x37, 0x98, 0x85, 0x5a, + 0x8a, 0xca, 0xd9, 0x23, 0xfe, 0x3e, 0xcc, 0x2a, 0x1a, 0x31, 0x90, 0x66, 0x28, 0xc8, 0xc0, 0xf5, + 0x16, 0x6e, 0xab, 0x0a, 0x21, 0x8a, 0xae, 0x65, 0x22, 0x8b, 0x5c, 0x3e, 0x59, 0xca, 0x16, 0xbc, + 0x74, 0x15, 0x56, 0x9b, 0x4d, 0x4c, 0xc8, 0x9a, 0xae, 0x6d, 0x2b, 0x72, 0xed, 0xbc, 0x4b, 0x7b, + 0xc3, 0x51, 0x2e, 0x5f, 0xfa, 0xe4, 0xe0, 0xe9, 0x0d, 0xcb, 0xb7, 0x2f, 0x0e, 0x9e, 0xde, 0x38, + 0xcb, 0xa8, 0x70, 0x23, 0xb9, 0x17, 0x8e, 0x87, 0x66, 0xc2, 0xf7, 0xc2, 0xf1, 0xf0, 0x4c, 0x44, + 0xdc, 0x82, 0xb4, 0x7b, 0xad, 0x86, 0x49, 0x4b, 0xd7, 0x08, 0xe6, 0x97, 0x20, 0x46, 0xb1, 0xd4, + 0x15, 0x89, 0xc1, 0x0d, 0x57, 0xa0, 0xdf, 0xcb, 0x45, 0xa9, 0xc8, 0xfa, 0xdd, 0x5a, 0x94, 0x2e, + 0xad, 0x4b, 0xbc, 0x00, 0xf1, 0xe6, 0x0e, 0x6e, 0x3e, 0x22, 0x1d, 0xd5, 0x04, 0x5d, 0x73, 0xc6, + 0xe2, 0xb3, 0x69, 0x98, 0xad, 0x12, 0x79, 0x7d, 0xe0, 0xe4, 0x9a, 0xae, 0x19, 0x6d, 0xd4, 0x34, + 0x02, 0x99, 0x4c, 0x43, 0x04, 0x49, 0xaa, 0xa2, 0x31, 0x5b, 0x89, 0x9a, 0x39, 0x70, 0x7b, 0x12, + 0x0a, 0xf4, 0x24, 0x0d, 0x91, 0x5d, 0xd4, 0xc0, 0xbb, 0x99, 0xb0, 0xa9, 0xca, 0x06, 0x7c, 0x1e, + 0x42, 0x2a, 0x91, 0x19, 0x9f, 0xa9, 0xca, 0xec, 0xdf, 0xbd, 0x1c, 0x5f, 0x43, 0x7b, 0xb6, 0x1b, + 0x55, 0x4c, 0x08, 0x92, 0x71, 0x8d, 0x8a, 0xf0, 0xdb, 0x10, 0xd9, 0xee, 0x68, 0x12, 0xc9, 0x44, + 0x17, 0x43, 0xf9, 0x64, 0x69, 0xbe, 0x60, 0xa5, 0x07, 0x4d, 0xcc, 0x82, 0x95, 0x98, 0x85, 0x35, + 0x5d, 0xd1, 0x2a, 0x6f, 0x3c, 0xef, 0xe5, 0xa6, 0xbe, 0xfd, 0x25, 0x97, 0x97, 0x15, 0x63, 0xa7, + 0xd3, 0x28, 0x34, 0x75, 0xd5, 0xca, 0x25, 0xeb, 0xdf, 0x32, 0x91, 0x1e, 0x59, 0x79, 0x47, 0x15, + 0xc8, 0xd7, 0x07, 0x4f, 0x6f, 0x70, 0x35, 0xd3, 0x7c, 0xf9, 0xa6, 0x27, 0x3a, 0x0b, 0x76, 0x74, + 0x7c, 0x78, 0x12, 0xdf, 0x83, 0xac, 0xff, 0x8a, 0x13, 0xa5, 0x0c, 0xc4, 0x90, 0x24, 0xb5, 0x31, + 0x21, 0x16, 0x95, 0xf6, 0x90, 0xe7, 0x21, 0x2c, 0x21, 0x03, 0x59, 0x61, 0x61, 0xdf, 0xe2, 0x9f, + 0xd3, 0x30, 0xe7, 0x6f, 0xb0, 0xf4, 0x3f, 0x8e, 0x09, 0xa5, 0x8a, 0xa0, 0x5d, 0x23, 0x13, 0x33, + 0xa9, 0xa2, 0xdf, 0xfc, 0x1c, 0xc4, 0xb6, 0x95, 0x6e, 0x9d, 0x7a, 0x1a, 0x5f, 0xe4, 0xf2, 0xf1, + 0x5a, 0x74, 0x5b, 0xe9, 0x56, 0x89, 0x5c, 0xbe, 0xe5, 0x09, 0xe0, 0x85, 0x31, 0x01, 0x2c, 0x89, + 0xef, 0x43, 0x2e, 0x60, 0xe9, 0x98, 0x21, 0xfc, 0x74, 0x1a, 0xf8, 0x2a, 0x91, 0xdf, 0xe9, 0xe2, + 0x66, 0x67, 0x82, 0x13, 0x45, 0x0f, 0xa8, 0x25, 0x63, 0x05, 0xd0, 0x19, 0xdb, 0x81, 0x08, 0x1d, + 0x21, 0x10, 0x91, 0x57, 0x7b, 0x38, 0xae, 0x79, 0xb8, 0x9d, 0xb3, 0xb9, 0xf5, 0xc0, 0x15, 0x6f, + 0x83, 0x30, 0x3a, 0xeb, 0x30, 0x6a, 0xf3, 0xc6, 0xb9, 0x78, 0x7b, 0xc6, 0x31, 0xde, 0xaa, 0x8a, + 0xdc, 0x46, 0x27, 0xe4, 0x6d, 0xa2, 0xdc, 0xb7, 0xc8, 0x0d, 0x1f, 0x4a, 0x6e, 0x30, 0x68, 0x8f, + 0xaf, 0x16, 0x68, 0xcf, 0xec, 0x58, 0xd0, 0x9f, 0x71, 0x70, 0xba, 0x4a, 0xe4, 0xfb, 0x2d, 0x09, + 0x19, 0x78, 0x95, 0x1d, 0xdc, 0x20, 0xc0, 0x0b, 0x90, 0xd0, 0xf0, 0x5e, 0xdd, 0x7d, 0xd4, 0xe3, + 0x1a, 0xde, 0x33, 0x95, 0xdc, 0x6c, 0x84, 0x86, 0xd9, 0x28, 0x2f, 0x79, 0xdc, 0x3f, 0x67, 0xbb, + 0xef, 0xda, 0x55, 0xcc, 0xb0, 0xab, 0xc0, 0x35, 0x63, 0xbb, 0x2d, 0xca, 0x70, 0xaa, 0x4a, 0xe4, + 0xb5, 0x5d, 0x8c, 0xda, 0xe3, 0x1d, 0x1c, 0xe7, 0x83, 0xe8, 0xf1, 0x81, 0xb7, 0x7d, 0x18, 0xd8, + 0x15, 0xe7, 0xe0, 0xfc, 0xd0, 0x84, 0xe3, 0xc1, 0x1f, 0x1c, 0xe3, 0xd5, 0x74, 0x6e, 0xf8, 0xa4, + 0x6e, 0x2b, 0x72, 0xa0, 0x3f, 0xae, 0x2c, 0x98, 0x0e, 0xcc, 0x82, 0x87, 0x20, 0x50, 0x56, 0x03, + 0xae, 0xf9, 0xd0, 0x44, 0xd7, 0x7c, 0x46, 0xc3, 0x7b, 0xeb, 0xbe, 0x37, 0x7d, 0xd1, 0x03, 0x3b, + 0x37, 0x4c, 0xfd, 0x08, 0x16, 0xf1, 0x32, 0x88, 0xc1, 0xab, 0x0e, 0x21, 0xdf, 0x71, 0x70, 0xc6, + 0x11, 0xdb, 0x40, 0x6d, 0xa4, 0x12, 0xfe, 0x0e, 0x24, 0x50, 0xc7, 0xd8, 0xd1, 0xdb, 0x8a, 0xb1, + 0x6f, 0x12, 0x51, 0xc9, 0xfc, 0xf4, 0xfd, 0x72, 0xda, 0x2a, 0x04, 0xab, 0x66, 0xc5, 0xda, 0x34, + 0xda, 0x8a, 0x26, 0xd7, 0x06, 0xa2, 0xfc, 0xdb, 0x10, 0x6d, 0x31, 0x0b, 0x8c, 0xa4, 0x64, 0x29, + 0x33, 0x0a, 0xd6, 0xdc, 0xa1, 0x92, 0xa0, 0x95, 0xc3, 0xac, 0x06, 0x96, 0x8a, 0x79, 0x32, 0x06, + 0xc6, 0x28, 0xc4, 0xf4, 0x30, 0x44, 0x53, 0x57, 0x9c, 0x67, 0xd7, 0x9a, 0x7b, 0xca, 0x01, 0xf3, + 0x83, 0x09, 0x66, 0xb3, 0x23, 0xe9, 0xce, 0xa1, 0x3f, 0x2e, 0x98, 0x7f, 0xa5, 0x98, 0x8e, 0x45, + 0xe5, 0x76, 0x53, 0x5c, 0x66, 0xa8, 0xdc, 0x53, 0x63, 0x0f, 0xfb, 0x13, 0x0e, 0x92, 0x55, 0x22, + 0x6f, 0x28, 0x1a, 0x4d, 0xc2, 0xe3, 0x87, 0xec, 0x2d, 0x8a, 0x92, 0x25, 0x36, 0x0d, 0x5a, 0x28, + 0x1f, 0xae, 0x64, 0xfb, 0xbd, 0x5c, 0xcc, 0xcc, 0x6c, 0xf2, 0x57, 0x2f, 0x77, 0x66, 0x1f, 0xa9, + 0xbb, 0x65, 0xd1, 0x16, 0x12, 0x6b, 0x31, 0x33, 0xdb, 0x89, 0x59, 0x0b, 0x86, 0xa1, 0xcd, 0xd8, + 0xd0, 0x6c, 0xbf, 0xc4, 0xf3, 0x70, 0xce, 0x35, 0x74, 0x02, 0xf5, 0x0d, 0xc7, 0x2a, 0xc1, 0x7d, + 0xad, 0xf5, 0x1f, 0x02, 0xb8, 0x32, 0x0a, 0xc0, 0xa9, 0x25, 0x03, 0xcf, 0xac, 0x5a, 0x32, 0x98, + 0x70, 0x40, 0xfc, 0x18, 0x66, 0x1d, 0x1b, 0xeb, 0xa6, 0x57, 0x35, 0xc9, 0xaf, 0xf7, 0x3d, 0x2e, + 0xaa, 0xd1, 0x57, 0x46, 0xe8, 0x84, 0xaf, 0x8c, 0xf0, 0x09, 0x5e, 0x19, 0xfc, 0x45, 0x80, 0x0e, + 0xc5, 0x6f, 0xba, 0x12, 0x61, 0x2d, 0x52, 0xa2, 0x63, 0x33, 0x32, 0xe8, 0x1a, 0xa3, 0xee, 0xae, + 0xd1, 0x69, 0x08, 0x63, 0x3e, 0x0d, 0x61, 0xfc, 0x08, 0x7d, 0x48, 0xe2, 0xd5, 0x36, 0x84, 0xb4, + 0xe6, 0xeb, 0x9d, 0x76, 0x13, 0x67, 0xc0, 0xaa, 0xf9, 0x6c, 0x44, 0x5b, 0xb5, 0x46, 0x47, 0xd9, + 0xa5, 0x97, 0x41, 0xd2, 0x6c, 0xd5, 0xac, 0x21, 0xbd, 0x3e, 0x59, 0x3a, 0xed, 0x20, 0xb2, 0x93, + 0x49, 0x59, 0x2f, 0x21, 0x5d, 0xc2, 0xef, 0x22, 0xb2, 0x53, 0xbe, 0x33, 0x9a, 0x55, 0x4b, 0x43, + 0x8f, 0x32, 0xff, 0x54, 0x11, 0x1f, 0xc0, 0xd5, 0xf1, 0x12, 0xc7, 0xec, 0x21, 0x9f, 0x70, 0x70, + 0x96, 0x1e, 0xc1, 0x76, 0x47, 0xc3, 0x5b, 0x88, 0xa8, 0x27, 0x3b, 0x6e, 0xcb, 0x90, 0x54, 0x51, + 0xb7, 0x3e, 0x7c, 0x19, 0x9e, 0xea, 0xf7, 0x72, 0x89, 0x2a, 0xea, 0x5a, 0xf7, 0x61, 0x42, 0xb5, + 0x3e, 0xa5, 0xf2, 0xf5, 0x51, 0x32, 0x66, 0x9d, 0x1a, 0x31, 0xe4, 0x91, 0xb8, 0x00, 0xf3, 0x23, + 0x93, 0x36, 0xe4, 0xd2, 0x57, 0x49, 0x08, 0x55, 0x89, 0xcc, 0x6f, 0x42, 0x62, 0xf0, 0x44, 0xf7, + 0x49, 0x66, 0xf7, 0xe3, 0x56, 0xb8, 0x3a, 0x7e, 0xdd, 0xe1, 0xf3, 0x23, 0x38, 0xe7, 0x77, 0x76, + 0xf3, 0xbe, 0xea, 0x3e, 0x92, 0xc2, 0xed, 0x49, 0x25, 0x9d, 0x2d, 0x0d, 0x48, 0xfb, 0xbe, 0xcb, + 0xae, 0x4f, 0x6a, 0xa9, 0x24, 0xac, 0x4c, 0x2c, 0xea, 0xec, 0x8a, 0xe1, 0x8c, 0xf7, 0x29, 0x71, + 0xd9, 0xd7, 0x8a, 0x47, 0x4a, 0xb8, 0x35, 0x89, 0x94, 0x7b, 0x1b, 0x6f, 0xe7, 0xed, 0xbf, 0x8d, + 0x47, 0x2a, 0x60, 0x9b, 0xa0, 0x1e, 0xf8, 0x03, 0x48, 0xba, 0x7b, 0xdd, 0x45, 0x5f, 0x65, 0x97, + 0x84, 0x90, 0x3f, 0x4c, 0xc2, 0x31, 0xfd, 0x00, 0xc0, 0xd5, 0xa4, 0xe6, 0x7c, 0xf5, 0x06, 0x02, + 0xc2, 0xb5, 0x43, 0x04, 0x1c, 0xbb, 0x1f, 0xc3, 0x5c, 0x50, 0xe7, 0x79, 0x6b, 0x8c, 0x73, 0x23, + 0xd2, 0xc2, 0xeb, 0x47, 0x91, 0x76, 0xb6, 0x7f, 0x08, 0xa9, 0xa1, 0x3e, 0xef, 0xd2, 0x18, 0x2b, + 0xa6, 0x88, 0x70, 0xfd, 0x50, 0x11, 0xb7, 0xf5, 0xa1, 0xc6, 0xcb, 0xdf, 0xba, 0x5b, 0x24, 0xc0, + 0xba, 0x6f, 0x13, 0xb4, 0x01, 0x71, 0xa7, 0xd9, 0xb9, 0xe8, 0xab, 0x66, 0x2f, 0x0b, 0x57, 0xc6, + 0x2e, 0xbb, 0x83, 0xec, 0xea, 0x3f, 0xfc, 0x83, 0x3c, 0x10, 0x08, 0x08, 0xf2, 0x68, 0x5b, 0xc0, + 0x7f, 0xce, 0xc1, 0xc2, 0xb8, 0x9e, 0xe0, 0x76, 0x70, 0x59, 0xf2, 0xd7, 0x10, 0xde, 0x3c, 0xaa, + 0x86, 0xe3, 0x4b, 0x03, 0x4e, 0x7b, 0x0a, 0xff, 0x92, 0x3f, 0x39, 0x43, 0x42, 0xc2, 0xcd, 0x09, + 0x84, 0xec, 0x3d, 0x2a, 0x77, 0x9f, 0xff, 0x96, 0x9d, 0x7a, 0xde, 0xcf, 0x72, 0x2f, 0xfa, 0x59, + 0xee, 0xd7, 0x7e, 0x96, 0xfb, 0xf2, 0x65, 0x76, 0xea, 0xc5, 0xcb, 0xec, 0xd4, 0xcf, 0x2f, 0xb3, + 0x53, 0x1f, 0x5e, 0x75, 0xdd, 0xc9, 0x6b, 0x3a, 0x51, 0xb7, 0xec, 0xdf, 0x6b, 0xa5, 0x62, 0xd7, + 0xfc, 0xdd, 0x96, 0xdd, 0xcb, 0x8d, 0x28, 0xfb, 0x1d, 0xf6, 0xb5, 0x7f, 0x02, 0x00, 0x00, 0xff, + 0xff, 0xb1, 0x77, 0xec, 0x33, 0x51, 0x16, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -3266,8 +3266,8 @@ func (m *MsgPruneWasmCodes) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.LatestCodeID != 0 { - i = encodeVarintTx(dAtA, i, uint64(m.LatestCodeID)) + if m.MaxCodeID != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.MaxCodeID)) i-- dAtA[i] = 0x10 } @@ -3821,8 +3821,8 @@ func (m *MsgPruneWasmCodes) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } - if m.LatestCodeID != 0 { - n += 1 + sovTx(uint64(m.LatestCodeID)) + if m.MaxCodeID != 0 { + n += 1 + sovTx(uint64(m.MaxCodeID)) } return n } @@ -7335,9 +7335,9 @@ func (m *MsgPruneWasmCodes) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field LatestCodeID", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field MaxCodeID", wireType) } - m.LatestCodeID = 0 + m.MaxCodeID = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -7347,7 +7347,7 @@ func (m *MsgPruneWasmCodes) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.LatestCodeID |= uint64(b&0x7F) << shift + m.MaxCodeID |= uint64(b&0x7F) << shift if b < 0x80 { break } diff --git a/x/wasm/types/tx_test.go b/x/wasm/types/tx_test.go index 597ae8fed7..ffda9eaef2 100644 --- a/x/wasm/types/tx_test.go +++ b/x/wasm/types/tx_test.go @@ -1139,20 +1139,20 @@ func TestMsgPruneWasmCodesValidation(t *testing.T) { }{ "all good": { src: MsgPruneWasmCodes{ - Authority: goodAddress, - LatestCodeID: 5, + Authority: goodAddress, + MaxCodeID: 5, }, }, "bad authority": { src: MsgPruneWasmCodes{ - Authority: badAddress, - LatestCodeID: 5, + Authority: badAddress, + MaxCodeID: 5, }, expErr: true, }, "empty authority": { src: MsgPruneWasmCodes{ - LatestCodeID: 5, + MaxCodeID: 5, }, expErr: true, }, From 77b129ebd4251c5bf061e8ff82faeda8467d75d7 Mon Sep 17 00:00:00 2001 From: Pino' Surace Date: Fri, 23 Jun 2023 12:49:35 +0200 Subject: [PATCH 12/18] More testing --- x/wasm/keeper/msg_server_integration_test.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/x/wasm/keeper/msg_server_integration_test.go b/x/wasm/keeper/msg_server_integration_test.go index 8741d8c5fa..d56393d0ae 100644 --- a/x/wasm/keeper/msg_server_integration_test.go +++ b/x/wasm/keeper/msg_server_integration_test.go @@ -854,7 +854,7 @@ func TestUpdateInstantiateConfig(t *testing.T) { } } -func TestPruneWasmCodesAuthority(t *testing.T) { +func TestPruneWasmCodesErrors(t *testing.T) { wasmApp := app.Setup(t) ctx := wasmApp.BaseApp.NewContext(false, tmproto.Header{}) @@ -866,28 +866,40 @@ func TestPruneWasmCodesAuthority(t *testing.T) { specs := map[string]struct { addr string pinCode bool + maxCodeID uint64 expPruned bool expErr bool }{ "authority can prune unpinned code": { addr: authority, pinCode: false, + maxCodeID: 5, expPruned: true, }, "authority cannot prune pinned code": { addr: authority, pinCode: true, + maxCodeID: 5, expPruned: false, }, "other address cannot prune unpinned code": { addr: myAddress.String(), pinCode: false, + maxCodeID: 5, expPruned: false, expErr: true, }, "other address cannot prune pinned code": { addr: myAddress.String(), pinCode: true, + maxCodeID: 5, + expPruned: false, + expErr: true, + }, + "invalid maxCodeID": { + addr: authority, + pinCode: false, + maxCodeID: 0, expPruned: false, expErr: true, }, @@ -899,7 +911,7 @@ func TestPruneWasmCodesAuthority(t *testing.T) { // when msgPruneCodes := &types.MsgPruneWasmCodes{ Authority: spec.addr, - MaxCodeID: 5, + MaxCodeID: spec.maxCodeID, } _, err := wasmApp.MsgServiceRouter().Handler(msgPruneCodes)(ctx, msgPruneCodes) From 6e2244eb45b07420b88b2055fc54971c801a2e64 Mon Sep 17 00:00:00 2001 From: Alexander Peters Date: Fri, 23 Jun 2023 13:35:12 +0200 Subject: [PATCH 13/18] Fix prune logic (#1460) --- x/wasm/keeper/keeper.go | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index 2b81d13ee9..f79dff57cd 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -1240,30 +1240,30 @@ func (k Keeper) iteratePinnedCodes(ctx sdk.Context, cb func(codeID uint64) bool) // PruneWasmCodes deletes code info for unpinned codes <= than maxCodeID func (k Keeper) PruneWasmCodes(ctx sdk.Context, maxCodeID uint64) error { - usedCodeIds := make(map[uint64]struct{}) - usedChecksums := make(map[string]bool) + usedCodeIDs := make(map[uint64]struct{}) + usedChecksums := make(map[string]struct{}) // collect code ids used by contracts k.IterateContractInfo(ctx, func(_ sdk.AccAddress, info types.ContractInfo) bool { - usedCodeIds[info.CodeID] = struct{}{} + usedCodeIDs[info.CodeID] = struct{}{} return false }) // collect pinned code ids k.iteratePinnedCodes(ctx, func(codeID uint64) bool { - usedCodeIds[codeID] = struct{}{} + usedCodeIDs[codeID] = struct{}{} return false }) // check if instances are used only by unpinned code ids <= maxCodeID k.IterateCodeInfos(ctx, func(codeID uint64, info types.CodeInfo) bool { - if _, ok := usedCodeIds[codeID]; !ok && codeID <= maxCodeID { - if !usedChecksums[string(info.CodeHash)] { - usedChecksums[string(info.CodeHash)] = false - } + if codeID > maxCodeID { // keep all + usedChecksums[string(info.CodeHash)] = struct{}{} return false } - usedChecksums[string(info.CodeHash)] = true + if _, ok := usedCodeIDs[codeID]; ok { + usedChecksums[string(info.CodeHash)] = struct{}{} + } return false }) @@ -1274,10 +1274,13 @@ func (k Keeper) PruneWasmCodes(ctx sdk.Context, maxCodeID uint64) error { // delete all unpinned code ids <= maxCodeID and all the // instances used only by unpinned code ids <= maxCodeID k.IterateCodeInfos(ctx, func(codeID uint64, info types.CodeInfo) bool { - if _, ok := usedCodeIds[codeID]; !ok && codeID <= maxCodeID { + if codeID > maxCodeID { + return true + } + if _, ok := usedCodeIDs[codeID]; !ok { k.deleteCodeInfo(ctx, codeID) deletedCodeInfoCounter++ - if !usedChecksums[string(info.CodeHash)] { + if _, ok := usedChecksums[string(info.CodeHash)]; !ok { if err := k.wasmVM.RemoveCode(info.CodeHash); err != nil { k.Logger(ctx).Error("failed to delete wasm file on disk", "checksum", info.CodeHash) } else { @@ -1287,8 +1290,8 @@ func (k Keeper) PruneWasmCodes(ctx sdk.Context, maxCodeID uint64) error { } return false }) - k.Logger(ctx).Info("deleted unused wasm files", "total", deletedWasmFileCounter) - k.Logger(ctx).Info("deleted unused code infos", "total", deletedCodeInfoCounter) + k.Logger(ctx).Info("executed prune wasm code", + "total wasm files", deletedWasmFileCounter, "total code infos", deletedCodeInfoCounter) return nil } From ca4d1e64b3141851a65d5ff27511c1e77781a6df Mon Sep 17 00:00:00 2001 From: Pino' Surace Date: Fri, 23 Jun 2023 14:03:17 +0200 Subject: [PATCH 14/18] Make tests more readable --- x/wasm/keeper/msg_server_integration_test.go | 168 +++++++------------ 1 file changed, 58 insertions(+), 110 deletions(-) diff --git a/x/wasm/keeper/msg_server_integration_test.go b/x/wasm/keeper/msg_server_integration_test.go index d56393d0ae..1043acd16d 100644 --- a/x/wasm/keeper/msg_server_integration_test.go +++ b/x/wasm/keeper/msg_server_integration_test.go @@ -933,146 +933,94 @@ func TestPruneWasmCodesErrors(t *testing.T) { func TestPruneWasmCodes(t *testing.T) { specs := map[string]struct { - wasmCode1 []byte - wasmCode2 []byte - pinCode1 bool - pinCode2 bool - expPrunedCodeInfo1 bool - expPrunedCodeInfo2 bool - expPrunedWasmCode1 bool - expPrunedWasmCode2 bool + wasmCodes [][]byte + pinCodes []bool + expPrunedCodeInfos []bool + expPrunedWasmCodes []bool maxCodeID uint64 }{ "duplicate codes - both pinned - max code id 2": { - wasmCode1: wasmContract, - wasmCode2: wasmContract, - pinCode1: true, - pinCode2: true, - expPrunedCodeInfo1: false, - expPrunedCodeInfo2: false, - expPrunedWasmCode1: false, - expPrunedWasmCode2: false, + wasmCodes: [][]byte{wasmContract, wasmContract}, + pinCodes: []bool{true, true}, + expPrunedCodeInfos: []bool{false, false}, + expPrunedWasmCodes: []bool{false, false}, maxCodeID: 2, }, "duplicate codes - only one pinned - max code id 2": { - wasmCode1: wasmContract, - wasmCode2: wasmContract, - pinCode1: true, - pinCode2: false, - expPrunedCodeInfo1: false, - expPrunedCodeInfo2: true, - expPrunedWasmCode1: false, - expPrunedWasmCode2: false, + wasmCodes: [][]byte{wasmContract, wasmContract}, + pinCodes: []bool{true, false}, + expPrunedCodeInfos: []bool{false, true}, + expPrunedWasmCodes: []bool{false, false}, maxCodeID: 2, }, "duplicate codes - both unpinned - max code id 2": { - wasmCode1: wasmContract, - wasmCode2: wasmContract, - pinCode1: false, - pinCode2: false, - expPrunedCodeInfo1: true, - expPrunedCodeInfo2: true, - expPrunedWasmCode1: true, - expPrunedWasmCode2: true, + wasmCodes: [][]byte{wasmContract, wasmContract}, + pinCodes: []bool{false, false}, + expPrunedCodeInfos: []bool{true, true}, + expPrunedWasmCodes: []bool{true, true}, maxCodeID: 2, }, "different codes - both pinned - max code id 2": { - wasmCode1: wasmContract, - wasmCode2: hackatomContract, - pinCode1: true, - pinCode2: true, - expPrunedCodeInfo1: false, - expPrunedCodeInfo2: false, - expPrunedWasmCode1: false, - expPrunedWasmCode2: false, + wasmCodes: [][]byte{wasmContract, hackatomContract}, + pinCodes: []bool{true, true}, + expPrunedCodeInfos: []bool{false, false}, + expPrunedWasmCodes: []bool{false, false}, maxCodeID: 2, }, "different codes - only one pinned - max code id 2": { - wasmCode1: wasmContract, - wasmCode2: hackatomContract, - pinCode1: true, - pinCode2: false, - expPrunedCodeInfo1: false, - expPrunedCodeInfo2: true, - expPrunedWasmCode1: false, - expPrunedWasmCode2: true, + wasmCodes: [][]byte{wasmContract, hackatomContract}, + pinCodes: []bool{true, false}, + expPrunedCodeInfos: []bool{false, true}, + expPrunedWasmCodes: []bool{false, true}, maxCodeID: 2, }, "different codes - both unpinned - max code id 2": { - wasmCode1: wasmContract, - wasmCode2: hackatomContract, - pinCode1: false, - pinCode2: false, - expPrunedCodeInfo1: true, - expPrunedCodeInfo2: true, - expPrunedWasmCode1: true, - expPrunedWasmCode2: true, + wasmCodes: [][]byte{wasmContract, hackatomContract}, + pinCodes: []bool{false, false}, + expPrunedCodeInfos: []bool{true, true}, + expPrunedWasmCodes: []bool{true, true}, maxCodeID: 2, }, "duplicate codes - both pinned - max code id 1": { - wasmCode1: wasmContract, - wasmCode2: wasmContract, - pinCode1: true, - pinCode2: true, - expPrunedCodeInfo1: false, - expPrunedCodeInfo2: false, - expPrunedWasmCode1: false, - expPrunedWasmCode2: false, + wasmCodes: [][]byte{wasmContract, wasmContract}, + pinCodes: []bool{true, true}, + expPrunedCodeInfos: []bool{false, false}, + expPrunedWasmCodes: []bool{false, false}, maxCodeID: 1, }, "duplicate codes - only one pinned - max code id 1": { - wasmCode1: wasmContract, - wasmCode2: wasmContract, - pinCode1: true, - pinCode2: false, - expPrunedCodeInfo1: false, - expPrunedCodeInfo2: false, - expPrunedWasmCode1: false, - expPrunedWasmCode2: false, + wasmCodes: [][]byte{wasmContract, wasmContract}, + pinCodes: []bool{true, false}, + expPrunedCodeInfos: []bool{false, false}, + expPrunedWasmCodes: []bool{false, false}, maxCodeID: 1, }, "duplicate codes - both unpinned - max code id 1": { - wasmCode1: wasmContract, - wasmCode2: wasmContract, - pinCode1: false, - pinCode2: false, - expPrunedCodeInfo1: true, - expPrunedCodeInfo2: false, - expPrunedWasmCode1: false, - expPrunedWasmCode2: false, + wasmCodes: [][]byte{wasmContract, wasmContract}, + pinCodes: []bool{false, false}, + expPrunedCodeInfos: []bool{true, false}, + expPrunedWasmCodes: []bool{false, false}, maxCodeID: 1, }, "different codes - both pinned - max code id 1": { - wasmCode1: wasmContract, - wasmCode2: hackatomContract, - pinCode1: true, - pinCode2: true, - expPrunedCodeInfo1: false, - expPrunedCodeInfo2: false, - expPrunedWasmCode1: false, - expPrunedWasmCode2: false, + wasmCodes: [][]byte{wasmContract, hackatomContract}, + pinCodes: []bool{true, true}, + expPrunedCodeInfos: []bool{false, false}, + expPrunedWasmCodes: []bool{false, false}, maxCodeID: 1, }, "different codes - only one pinned - max code id 1": { - wasmCode1: wasmContract, - wasmCode2: hackatomContract, - pinCode1: true, - pinCode2: false, - expPrunedCodeInfo1: false, - expPrunedCodeInfo2: false, - expPrunedWasmCode1: false, - expPrunedWasmCode2: false, + wasmCodes: [][]byte{wasmContract, hackatomContract}, + pinCodes: []bool{true, false}, + expPrunedCodeInfos: []bool{false, false}, + expPrunedWasmCodes: []bool{false, false}, maxCodeID: 1, }, "different codes - both unpinned - max code id 1": { - wasmCode1: wasmContract, - wasmCode2: hackatomContract, - pinCode1: false, - pinCode2: false, - expPrunedCodeInfo1: true, - expPrunedCodeInfo2: false, - expPrunedWasmCode1: true, - expPrunedWasmCode2: false, + wasmCodes: [][]byte{wasmContract, hackatomContract}, + pinCodes: []bool{false, false}, + expPrunedCodeInfos: []bool{true, false}, + expPrunedWasmCodes: []bool{true, false}, maxCodeID: 1, }, } @@ -1082,8 +1030,8 @@ func TestPruneWasmCodes(t *testing.T) { ctx := wasmApp.BaseApp.NewContext(false, tmproto.Header{}) authority := wasmApp.WasmKeeper.GetAuthority() - code1, checksum1 := setupWasmCode(t, authority, ctx, wasmApp, spec.wasmCode1, spec.pinCode1) - code2, checksum2 := setupWasmCode(t, authority, ctx, wasmApp, spec.wasmCode2, spec.pinCode2) + code1, checksum1 := setupWasmCode(t, authority, ctx, wasmApp, spec.wasmCodes[0], spec.pinCodes[0]) + code2, checksum2 := setupWasmCode(t, authority, ctx, wasmApp, spec.wasmCodes[1], spec.pinCodes[1]) // when msgPruneCodes := &types.MsgPruneWasmCodes{ @@ -1095,11 +1043,11 @@ func TestPruneWasmCodes(t *testing.T) { // then require.NoError(t, err) - assertCodeInfoPruning(t, ctx, wasmApp, code1, spec.expPrunedCodeInfo1) - assertWasmCodePruning(t, ctx, wasmApp, checksum1, spec.expPrunedWasmCode1) + assertCodeInfoPruning(t, ctx, wasmApp, code1, spec.expPrunedCodeInfos[0]) + assertWasmCodePruning(t, ctx, wasmApp, checksum1, spec.expPrunedWasmCodes[0]) - assertCodeInfoPruning(t, ctx, wasmApp, code2, spec.expPrunedCodeInfo2) - assertWasmCodePruning(t, ctx, wasmApp, checksum2, spec.expPrunedWasmCode2) + assertCodeInfoPruning(t, ctx, wasmApp, code2, spec.expPrunedCodeInfos[1]) + assertWasmCodePruning(t, ctx, wasmApp, checksum2, spec.expPrunedWasmCodes[1]) }) } } From 47b1326b189f717d199172c3dd404e39da42738f Mon Sep 17 00:00:00 2001 From: Pino' Surace Date: Mon, 26 Jun 2023 18:25:17 +0200 Subject: [PATCH 15/18] Add simple bench test --- x/wasm/keeper/bench_test.go | 25 ++++++++++++++++++++++++ x/wasm/keeper/wasmtesting/mock_engine.go | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/x/wasm/keeper/bench_test.go b/x/wasm/keeper/bench_test.go index ff0240afaf..c48b024ad2 100644 --- a/x/wasm/keeper/bench_test.go +++ b/x/wasm/keeper/bench_test.go @@ -8,7 +8,9 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/stretchr/testify/require" + "github.com/CosmWasm/wasmd/x/wasm/keeper/wasmtesting" "github.com/CosmWasm/wasmd/x/wasm/types" + wasmvm "github.com/CosmWasm/wasmvm" ) // BenchmarkVerification benchmarks secp256k1 verification which is 1000 gas based on cpu time. @@ -100,3 +102,26 @@ func BenchmarkCompilation(b *testing.B) { }) } } + +// Calculate the time it takes to prune about 100k wasm codes +func BenchmarkPruningWasmCodes(b *testing.B) { + mockWasmVM := wasmtesting.MockWasmer{ + RemoveCodeFn: func(checksum wasmvm.Checksum) error { + return nil + }, + } + wasmtesting.MakeInstantiable(&mockWasmVM) + ctx, keepers := CreateTestInput(b, false, AvailableCapabilities, WithWasmEngine(&mockWasmVM)) + + for i := 0; i < 100000; i++ { + contract := StoreRandomContract(b, ctx, keepers, &mockWasmVM) + if i%10 == 0 { + keepers.ContractKeeper.PinCode(ctx, contract.CodeID) + } + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + keepers.WasmKeeper.PruneWasmCodes(ctx, 100000) + } +} diff --git a/x/wasm/keeper/wasmtesting/mock_engine.go b/x/wasm/keeper/wasmtesting/mock_engine.go index da13616ec7..8d7d04af93 100644 --- a/x/wasm/keeper/wasmtesting/mock_engine.go +++ b/x/wasm/keeper/wasmtesting/mock_engine.go @@ -167,7 +167,7 @@ func (m *MockWasmer) Unpin(checksum wasmvm.Checksum) error { } func (m *MockWasmer) RemoveCode(checksum wasmvm.Checksum) error { - if m.UnpinFn == nil { + if m.RemoveCodeFn == nil { panic("not supposed to be called!") } return m.RemoveCodeFn(checksum) From 37b872e0867f4509d4d0116f5642ae30527e6fbe Mon Sep 17 00:00:00 2001 From: Pino' Surace Date: Tue, 27 Jun 2023 10:34:57 +0200 Subject: [PATCH 16/18] Fix bench test --- x/wasm/keeper/bench_test.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/x/wasm/keeper/bench_test.go b/x/wasm/keeper/bench_test.go index c48b024ad2..9ca197f16d 100644 --- a/x/wasm/keeper/bench_test.go +++ b/x/wasm/keeper/bench_test.go @@ -114,14 +114,11 @@ func BenchmarkPruningWasmCodes(b *testing.B) { ctx, keepers := CreateTestInput(b, false, AvailableCapabilities, WithWasmEngine(&mockWasmVM)) for i := 0; i < 100000; i++ { - contract := StoreRandomContract(b, ctx, keepers, &mockWasmVM) - if i%10 == 0 { - keepers.ContractKeeper.PinCode(ctx, contract.CodeID) - } + _ = StoreRandomContract(b, ctx, keepers, &mockWasmVM) } b.ResetTimer() for i := 0; i < b.N; i++ { - keepers.WasmKeeper.PruneWasmCodes(ctx, 100000) + _ = keepers.WasmKeeper.PruneWasmCodes(ctx, 100000) } } From e7d4b32c93d311cb3975252b7a92dfba316f8127 Mon Sep 17 00:00:00 2001 From: Pino' Surace Date: Tue, 27 Jun 2023 14:58:17 +0200 Subject: [PATCH 17/18] Improve bench tests --- x/wasm/keeper/bench_test.go | 138 +++++++++++++++++++++++++++++++++--- 1 file changed, 127 insertions(+), 11 deletions(-) diff --git a/x/wasm/keeper/bench_test.go b/x/wasm/keeper/bench_test.go index 9ca197f16d..714c339f3c 100644 --- a/x/wasm/keeper/bench_test.go +++ b/x/wasm/keeper/bench_test.go @@ -6,7 +6,9 @@ import ( dbm "github.com/cometbft/cometbft-db" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" + "github.com/syndtr/goleveldb/leveldb/opt" "github.com/CosmWasm/wasmd/x/wasm/keeper/wasmtesting" "github.com/CosmWasm/wasmd/x/wasm/types" @@ -105,20 +107,134 @@ func BenchmarkCompilation(b *testing.B) { // Calculate the time it takes to prune about 100k wasm codes func BenchmarkPruningWasmCodes(b *testing.B) { - mockWasmVM := wasmtesting.MockWasmer{ - RemoveCodeFn: func(checksum wasmvm.Checksum) error { - return nil + specs := map[string]struct { + db func() dbm.DB + setupContracts func(t testing.TB, ctx sdk.Context, keepers TestKeepers, mock types.WasmerEngine) + }{ + "100k codes unpinned - memory db": { + db: func() dbm.DB { return dbm.NewMemDB() }, + setupContracts: func(t testing.TB, ctx sdk.Context, keepers TestKeepers, mock types.WasmerEngine) { + for i := 0; i < 100000; i++ { + _ = StoreRandomContract(b, ctx, keepers, mock) + } + }, + }, + "100k codes unpinned - level db": { + db: func() dbm.DB { + levelDB, err := dbm.NewGoLevelDBWithOpts("testing", b.TempDir(), &opt.Options{BlockCacher: opt.NoCacher}) + require.NoError(b, err) + return levelDB + }, + setupContracts: func(t testing.TB, ctx sdk.Context, keepers TestKeepers, mock types.WasmerEngine) { + for i := 0; i < 100000; i++ { + _ = StoreRandomContract(b, ctx, keepers, mock) + } + }, + }, + "100k codes - 20% instantiated - memory db": { + db: func() dbm.DB { return dbm.NewMemDB() }, + setupContracts: func(t testing.TB, ctx sdk.Context, keepers TestKeepers, mock types.WasmerEngine) { + for i := 0; i < 100000; i++ { + if i%5 == 0 { + _ = SeedNewContractInstance(b, ctx, keepers, mock) + continue + } + _ = StoreRandomContract(b, ctx, keepers, mock) + } + }, + }, + "100k codes - 20% instantiated - level db": { + db: func() dbm.DB { + levelDB, err := dbm.NewGoLevelDBWithOpts("testing", b.TempDir(), &opt.Options{BlockCacher: opt.NoCacher}) + require.NoError(b, err) + return levelDB + }, + setupContracts: func(t testing.TB, ctx sdk.Context, keepers TestKeepers, mock types.WasmerEngine) { + for i := 0; i < 100000; i++ { + if i%5 == 0 { + _ = SeedNewContractInstance(b, ctx, keepers, mock) + continue + } + _ = StoreRandomContract(b, ctx, keepers, mock) + } + }, + }, + "100k codes - 50% instantiated - memory db": { + db: func() dbm.DB { return dbm.NewMemDB() }, + setupContracts: func(t testing.TB, ctx sdk.Context, keepers TestKeepers, mock types.WasmerEngine) { + for i := 0; i < 100000; i++ { + if i%2 == 0 { + _ = StoreRandomContract(b, ctx, keepers, mock) + continue + } + _ = SeedNewContractInstance(b, ctx, keepers, mock) + } + }, + }, + "100k codes - 50% instantiated - level db": { + db: func() dbm.DB { + levelDB, err := dbm.NewGoLevelDBWithOpts("testing", b.TempDir(), &opt.Options{BlockCacher: opt.NoCacher}) + require.NoError(b, err) + return levelDB + }, + setupContracts: func(t testing.TB, ctx sdk.Context, keepers TestKeepers, mock types.WasmerEngine) { + for i := 0; i < 100000; i++ { + if i%2 == 0 { + _ = StoreRandomContract(b, ctx, keepers, mock) + continue + } + _ = SeedNewContractInstance(b, ctx, keepers, mock) + } + }, + }, + "100k codes - 80% instantiated - memory db": { + db: func() dbm.DB { return dbm.NewMemDB() }, + setupContracts: func(t testing.TB, ctx sdk.Context, keepers TestKeepers, mock types.WasmerEngine) { + for i := 0; i < 100000; i++ { + if i%5 == 0 { + _ = StoreRandomContract(b, ctx, keepers, mock) + continue + } + _ = SeedNewContractInstance(b, ctx, keepers, mock) + } + }, + }, + "100k codes - 80% instantiated - level db": { + db: func() dbm.DB { + levelDB, err := dbm.NewGoLevelDBWithOpts("testing", b.TempDir(), &opt.Options{BlockCacher: opt.NoCacher}) + require.NoError(b, err) + return levelDB + }, + setupContracts: func(t testing.TB, ctx sdk.Context, keepers TestKeepers, mock types.WasmerEngine) { + for i := 0; i < 100000; i++ { + if i%5 == 0 { + _ = StoreRandomContract(b, ctx, keepers, mock) + continue + } + _ = SeedNewContractInstance(b, ctx, keepers, mock) + } + }, }, } - wasmtesting.MakeInstantiable(&mockWasmVM) - ctx, keepers := CreateTestInput(b, false, AvailableCapabilities, WithWasmEngine(&mockWasmVM)) - for i := 0; i < 100000; i++ { - _ = StoreRandomContract(b, ctx, keepers, &mockWasmVM) - } + for name, spec := range specs { + b.Run(name, func(b *testing.B) { + mockWasmVM := wasmtesting.MockWasmer{ + RemoveCodeFn: func(checksum wasmvm.Checksum) error { + return nil + }, + } + wasmtesting.MakeInstantiable(&mockWasmVM) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = keepers.WasmKeeper.PruneWasmCodes(ctx, 100000) + wasmConfig := types.WasmConfig{MemoryCacheSize: 0} + ctx, keepers := createTestInput(b, false, AvailableCapabilities, wasmConfig, spec.db(), WithWasmEngine(&mockWasmVM)) + + spec.setupContracts(b, ctx, keepers, &mockWasmVM) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = keepers.WasmKeeper.PruneWasmCodes(ctx, 100000) + } + }) } } From 4dfc1f489bfdf4fe066c332b0ff08894366af643 Mon Sep 17 00:00:00 2001 From: Pino' Surace Date: Tue, 27 Jun 2023 15:52:59 +0200 Subject: [PATCH 18/18] Increase timeout --- .circleci/config.yml | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0e4061f299..92f00f76b1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -108,7 +108,7 @@ jobs: name: Benchmarks for gas calculations command: | cd ./x/wasm/keeper - go test -bench . + go test -timeout 30m -bench . - run: name: Benchmarks to compare with native modules command: | diff --git a/Makefile b/Makefile index d884193143..f9aa6b8d7f 100644 --- a/Makefile +++ b/Makefile @@ -138,7 +138,7 @@ test-cover: @go test -mod=readonly -timeout 30m -race -coverprofile=coverage.txt -covermode=atomic -tags='ledger test_ledger_mock' ./... benchmark: - @go test -mod=readonly -bench=. ./... + @go test -mod=readonly -timeout 30m -bench=. ./... test-sim-import-export: runsim @echo "Running application import/export simulation. This may take several minutes..."