Skip to content

Commit

Permalink
Extend ContractInfo with custom data
Browse files Browse the repository at this point in the history
  • Loading branch information
alpe committed Apr 15, 2021
1 parent 4b8d024 commit 5a13c3f
Show file tree
Hide file tree
Showing 21 changed files with 735 additions and 252 deletions.
3 changes: 2 additions & 1 deletion cmd/wasmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"path/filepath"

"github.com/CosmWasm/wasmd/x/wasm"
clientcodec "github.com/CosmWasm/wasmd/x/wasm/client/codec"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
vestingcli "github.com/cosmos/cosmos-sdk/x/auth/vesting/client/cli"
bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
Expand Down Expand Up @@ -48,7 +49,7 @@ func NewRootCmd() (*cobra.Command, app.EncodingConfig) {
config.Seal()

initClientCtx := client.Context{}.
WithJSONMarshaler(encodingConfig.Marshaler).
WithJSONMarshaler(clientcodec.NewProtoCodec(encodingConfig.Marshaler, encodingConfig.InterfaceRegistry)).
WithInterfaceRegistry(encodingConfig.InterfaceRegistry).
WithTxConfig(encodingConfig.TxConfig).
WithLegacyAmino(encodingConfig.Amino).
Expand Down
1 change: 1 addition & 0 deletions docs/proto/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ ContractInfo stores a WASM contract instance
| `label` | [string](#string) | | Label is optional metadata to be stored with a contract instance. |
| `created` | [AbsoluteTxPosition](#cosmwasm.wasm.v1beta1.AbsoluteTxPosition) | | Created Tx position when the contract was instantiated. This data should kept internal and not be exposed via query results. Just use for sorting |
| `ibc_port_id` | [string](#string) | | |
| `extension` | [google.protobuf.Any](#google.protobuf.Any) | | Extension is an extension point to store custom metadata within the persistence model. |



Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ require (
github.com/grpc-ecosystem/grpc-gateway v1.16.0
github.com/pkg/errors v0.9.1
github.com/rakyll/statik v0.1.7
github.com/regen-network/cosmos-proto v0.3.1 // indirect
github.com/rs/zerolog v1.21.0
github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa
github.com/spf13/cast v1.3.1
Expand Down
14 changes: 10 additions & 4 deletions proto/cosmwasm/wasm/v1beta1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,11 @@ message QueryContractInfoResponse {

// address is the address of the contract
string address = 1;
ContractInfo contract_info = 2
[ (gogoproto.embed) = true, (gogoproto.jsontag) = "" ];
ContractInfo contract_info = 2 [
(gogoproto.embed) = true,
(gogoproto.nullable) = false,
(gogoproto.jsontag) = ""
];
}

// QueryContractHistoryRequest is the request type for the Query/ContractHistory
Expand Down Expand Up @@ -103,8 +106,11 @@ message ContractInfoWithAddress {
option (gogoproto.equal) = true;

string address = 1;
ContractInfo contract_info = 2
[ (gogoproto.embed) = true, (gogoproto.jsontag) = "" ];
ContractInfo contract_info = 2 [
(gogoproto.embed) = true,
(gogoproto.nullable) = false,
(gogoproto.jsontag) = ""
];
}
// QueryContractsByCodeResponse is the response type for the
// Query/ContractsByCode RPC method
Expand Down
7 changes: 7 additions & 0 deletions proto/cosmwasm/wasm/v1beta1/types.proto
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
syntax = "proto3";
package cosmwasm.wasm.v1beta1;

import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";
import "google/protobuf/any.proto";

option go_package = "github.com/CosmWasm/wasmd/x/wasm/types";
option (gogoproto.goproto_getters_all) = false;
Expand Down Expand Up @@ -83,6 +85,11 @@ message ContractInfo {
// use for sorting
AbsoluteTxPosition created = 5;
string ibc_port_id = 6 [ (gogoproto.customname) = "IBCPortID" ];

// Extension is an extension point to store custom metadata within the
// persistence model.
google.protobuf.Any extension = 7
[ (cosmos_proto.accepts_interface) = "ContractInfoExtension" ];
}

// ContractCodeHistoryOperationType actions that caused a code change
Expand Down
6 changes: 3 additions & 3 deletions x/wasm/client/cli/genesis_msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type GenesisReader interface {
// GenesisMutator extension point to modify the wasm module genesis state.
// This gives flexibility to customize the data structure in the genesis file a bit.
type GenesisMutator interface {
// AlterModuleState loads the genesis from the default or set home dir,
// AlterWasmModuleState loads the genesis from the default or set home dir,
// unmarshalls the wasm module section into the object representation
// calls the callback function to modify it
// and marshals the modified state back into the genesis file
Expand Down Expand Up @@ -147,7 +147,7 @@ func GenesisInstantiateContractCmd(defaultNodeHome string, genesisMutator Genesi
return cmd
}

// GenesisInstantiateContractCmd cli command to add a `MsgExecuteContract` to the wasm section of the genesis
// GenesisExecuteContractCmd cli command to add a `MsgExecuteContract` to the wasm section of the genesis
// that is executed on block 0.
func GenesisExecuteContractCmd(defaultNodeHome string, genesisMutator GenesisMutator) *cobra.Command {
cmd := &cobra.Command{
Expand Down Expand Up @@ -420,7 +420,7 @@ func NewDefaultGenesisIO() *DefaultGenesisIO {
return &DefaultGenesisIO{DefaultGenesisReader: DefaultGenesisReader{}}
}

// AlterModuleState loads the genesis from the default or set home dir,
// AlterWasmModuleState loads the genesis from the default or set home dir,
// unmarshalls the wasm module section into the object representation
// calls the callback function to modify it
// and marshals the modified state back into the genesis file
Expand Down
51 changes: 7 additions & 44 deletions x/wasm/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ import (
"github.com/CosmWasm/wasmd/x/wasm/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/gogo/protobuf/proto"
"github.com/spf13/cobra"
flag "github.com/spf13/pflag"
)
Expand Down Expand Up @@ -66,7 +64,7 @@ func GetCmdListCode() *cobra.Command {
if err != nil {
return err
}
return clientCtx.WithJSONMarshaler(&VanillaStdJsonMarshaller{}).PrintProto(res)
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
Expand Down Expand Up @@ -107,7 +105,7 @@ func GetCmdListContractByCode() *cobra.Command {
if err != nil {
return err
}
return clientCtx.WithJSONMarshaler(&VanillaStdJsonMarshaller{}).PrintProto(res)
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
Expand Down Expand Up @@ -183,7 +181,7 @@ func GetCmdGetContractInfo() *cobra.Command {
if err != nil {
return err
}
return clientCtx.WithJSONMarshaler(&VanillaStdJsonMarshaller{}).PrintProto(res)
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
Expand Down Expand Up @@ -240,7 +238,7 @@ func GetCmdGetContractStateAll() *cobra.Command {
if err != nil {
return err
}
return clientCtx.WithJSONMarshaler(&VanillaStdJsonMarshaller{}).PrintProto(res)
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
Expand Down Expand Up @@ -281,7 +279,7 @@ func GetCmdGetContractStateRaw() *cobra.Command {
if err != nil {
return err
}
return clientCtx.WithJSONMarshaler(&VanillaStdJsonMarshaller{}).PrintProto(res)
return clientCtx.PrintProto(res)
},
}
decoder.RegisterFlags(cmd.PersistentFlags(), "key argument")
Expand Down Expand Up @@ -329,7 +327,7 @@ func GetCmdGetContractStateSmart() *cobra.Command {
if err != nil {
return err
}
return clientCtx.WithJSONMarshaler(&VanillaStdJsonMarshaller{}).PrintProto(res)
return clientCtx.PrintProto(res)
},
}
decoder.RegisterFlags(cmd.PersistentFlags(), "query argument")
Expand Down Expand Up @@ -371,7 +369,7 @@ func GetCmdGetContractHistory() *cobra.Command {
return err
}

return clientCtx.WithJSONMarshaler(&VanillaStdJsonMarshaller{}).PrintProto(res)
return clientCtx.PrintProto(res)
},
}

Expand Down Expand Up @@ -423,41 +421,6 @@ func asciiDecodeString(s string) ([]byte, error) {
return []byte(s), nil
}

type VanillaStdJsonMarshaller struct {
}

func (x VanillaStdJsonMarshaller) MarshalInterfaceJSON(i proto.Message) ([]byte, error) {
any, err := codectypes.NewAnyWithValue(i)
if err != nil {
return nil, err
}
return x.MarshalJSON(any)
}

func (x VanillaStdJsonMarshaller) MarshalJSON(o proto.Message) ([]byte, error) {
return json.MarshalIndent(o, "", " ")
}

func (x VanillaStdJsonMarshaller) MustMarshalJSON(o proto.Message) []byte {
b, err := x.MarshalJSON(o)
if err != nil {
panic(err)
}
return b
}

func (x VanillaStdJsonMarshaller) UnmarshalInterfaceJSON(bz []byte, ptr interface{}) error {
panic("not supported")
}

func (x VanillaStdJsonMarshaller) UnmarshalJSON(bz []byte, ptr proto.Message) error {
panic("not supported")
}

func (x VanillaStdJsonMarshaller) MustUnmarshalJSON(bz []byte, ptr proto.Message) {
panic("not supported")
}

// sdk ReadPageRequest expects binary but we encoded to base64 in our marshaller
func withPageKeyDecoded(flagSet *flag.FlagSet) *flag.FlagSet {
encoded, err := flagSet.GetString(flags.FlagPageKey)
Expand Down
76 changes: 76 additions & 0 deletions x/wasm/client/codec/marshaller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package codec

import (
"bytes"
"fmt"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/gogo/protobuf/jsonpb"
"github.com/gogo/protobuf/proto"
)

var _ codec.Marshaler = (*ProtoCodec)(nil)

// ProtoCodec that omits empty values
type ProtoCodec struct {
codec.Marshaler
interfaceRegistry types.InterfaceRegistry
}

func NewProtoCodec(marshaler codec.Marshaler, registry types.InterfaceRegistry) *ProtoCodec {
return &ProtoCodec{Marshaler: marshaler, interfaceRegistry: registry}
}

// MarshalJSON implements JSONMarshaler.MarshalJSON method,
// it marshals to JSON using proto codec.
func (pc *ProtoCodec) MarshalJSON(o proto.Message) ([]byte, error) {
m, ok := o.(codec.ProtoMarshaler)
if !ok {
return nil, fmt.Errorf("cannot protobuf JSON encode unsupported type: %T", o)
}
return ProtoMarshalJSON(m, pc.interfaceRegistry)
}

// MustMarshalJSON implements JSONMarshaler.MustMarshalJSON method,
// it executes MarshalJSON except it panics upon failure.
func (pc *ProtoCodec) MustMarshalJSON(o proto.Message) []byte {
bz, err := pc.MarshalJSON(o)
if err != nil {
panic(err)
}
return bz
}

// MarshalInterfaceJSON is a convenience function for proto marshalling interfaces. It
// packs the provided value in an Any and then marshals it to bytes.
// NOTE: to marshal a concrete type, you should use MarshalJSON instead
func (pc *ProtoCodec) MarshalInterfaceJSON(x proto.Message) ([]byte, error) {
any, err := types.NewAnyWithValue(x)
if err != nil {
return nil, err
}
return pc.MarshalJSON(any)
}

// ProtoMarshalJSON provides an auxiliary function to return Proto3 JSON encoded
// bytes of a message.
func ProtoMarshalJSON(msg proto.Message, resolver jsonpb.AnyResolver) ([]byte, error) {
// method copied from sdk codec/json.go with EmitDefaults set to `false`
// so that empty fields are not rendered

// We use the OrigName because camel casing fields just doesn't make sense.
// EmitDefaults is also often the more expected behavior for CLI users
jm := &jsonpb.Marshaler{OrigName: true, EmitDefaults: false, AnyResolver: resolver}
err := types.UnpackInterfaces(msg, types.ProtoJSONPacker{JSONPBMarshaler: jm})
if err != nil {
return nil, err
}

buf := new(bytes.Buffer)

if err := jm.Marshal(buf, msg); err != nil {
return nil, err
}

return buf.Bytes(), nil
}
6 changes: 6 additions & 0 deletions x/wasm/keeper/contract_keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type decoratedKeeper interface {
pinCode(ctx sdk.Context, codeID uint64) error
unpinCode(ctx sdk.Context, codeID uint64) error
execute(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, msg []byte, coins sdk.Coins) (*sdk.Result, error)
setContractInfoExtension(ctx sdk.Context, contract sdk.AccAddress, extra types.ContractInfoExtension) error
}

type PermissionedKeeper struct {
Expand Down Expand Up @@ -66,3 +67,8 @@ func (p PermissionedKeeper) PinCode(ctx sdk.Context, codeID uint64) error {
func (p PermissionedKeeper) UnpinCode(ctx sdk.Context, codeID uint64) error {
return p.nested.unpinCode(ctx, codeID)
}

// SetExtraContractAttributes updates the extra attributes that can be stored with the contract info
func (p PermissionedKeeper) SetContractInfoExtension(ctx sdk.Context, contract sdk.AccAddress, extra types.ContractInfoExtension) error {
return p.nested.setContractInfoExtension(ctx, contract, extra)
}
Loading

0 comments on commit 5a13c3f

Please sign in to comment.