From 62d0c308a835b72693ded2b64bdfccee3dae1b21 Mon Sep 17 00:00:00 2001 From: anilCSE Date: Fri, 17 Jan 2020 10:58:50 +0530 Subject: [PATCH] Add source ref --- x/wasm/client/cli/tx.go | 40 ++++++++++++++++++++++++-- x/wasm/handler.go | 2 +- x/wasm/internal/keeper/genesis.go | 2 +- x/wasm/internal/keeper/keeper.go | 5 ++-- x/wasm/internal/keeper/keeper_test.go | 8 +++--- x/wasm/internal/keeper/querier_test.go | 2 +- x/wasm/internal/types/msg.go | 4 +++ x/wasm/internal/types/types.go | 6 +++- 8 files changed, 56 insertions(+), 13 deletions(-) diff --git a/x/wasm/client/cli/tx.go b/x/wasm/client/cli/tx.go index a51890d..ed5a01a 100644 --- a/x/wasm/client/cli/tx.go +++ b/x/wasm/client/cli/tx.go @@ -4,6 +4,7 @@ import ( "bufio" "fmt" "io/ioutil" + "net/url" "strconv" "github.com/spf13/cobra" @@ -21,13 +22,20 @@ import ( ) const ( - flagTo = "to" - flagAmount = "amount" + flagTo = "to" + flagAmount = "amount" + flagSource = "source" + flagBuilder = "builder" ) // limit max bytes read to prevent gzip bombs const maxSize = 400 * 1024 +// whitelist +var validBuildTags = map[string]bool{ + "cosmwasm-opt:0.6.0": true, "cosmwasm-opt:0.5.2": true, +} + // GetTxCmd returns the transaction commands for this module func GetTxCmd(cdc *codec.Codec) *cobra.Command { txCmd := &cobra.Command{ @@ -48,7 +56,7 @@ func GetTxCmd(cdc *codec.Codec) *cobra.Command { // StoreCodeCmd will upload code to be reused. func StoreCodeCmd(cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ - Use: "store [from_key_or_address] [wasm file]", + Use: "store [from_key_or_address] [wasm file] --source [source] --builder [builder]", Short: "Upload a wasm binary", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { @@ -62,6 +70,26 @@ func StoreCodeCmd(cdc *codec.Codec) *cobra.Command { return err } + source := viper.GetString(flagSource) + + // ensure source to be a valid uri + if source != "" { + _, err := url.Parse(source) + + if err != nil { + return fmt.Errorf("invalid url supplied for source %s", source) + } + } + + builder := viper.GetString(flagBuilder) + + // ensure builder to be a valid build tag + if builder != "" { + if !validBuildTags[builder] { + return fmt.Errorf("invalid tag supplied for builder %s", source) + } + } + // limit the input size if len(wasm) > maxSize { return fmt.Errorf("input size exceeds the max size allowed (allowed:%d, actual: %d)", @@ -83,10 +111,16 @@ func StoreCodeCmd(cdc *codec.Codec) *cobra.Command { msg := types.MsgStoreCode{ Sender: cliCtx.GetFromAddress(), WASMByteCode: wasm, + Source: source, + Builder: builder, } return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) }, } + + cmd.Flags().String(flagSource, "", "A valid URI reference to the contract's source code, optional") + cmd.Flags().String(flagBuilder, "", "A valid docker tag for the build system, optional") + return cmd } diff --git a/x/wasm/handler.go b/x/wasm/handler.go index 7078bfc..0ed3e3e 100644 --- a/x/wasm/handler.go +++ b/x/wasm/handler.go @@ -40,7 +40,7 @@ func NewHandler(k Keeper) sdk.Handler { } func handleStoreCode(ctx sdk.Context, k Keeper, msg *MsgStoreCode) sdk.Result { - codeID, err := k.Create(ctx, msg.Sender, msg.WASMByteCode) + codeID, err := k.Create(ctx, msg.Sender, msg.WASMByteCode, msg.Source, msg.Builder) if err != nil { return err.Result() } diff --git a/x/wasm/internal/keeper/genesis.go b/x/wasm/internal/keeper/genesis.go index e67ee85..ad72c7d 100644 --- a/x/wasm/internal/keeper/genesis.go +++ b/x/wasm/internal/keeper/genesis.go @@ -14,7 +14,7 @@ import ( // CONTRACT: all types of accounts must have been already initialized/created func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) { for _, code := range data.Codes { - newId, err := keeper.Create(ctx, code.CodeInfo.Creator, code.CodesBytes) + newId, err := keeper.Create(ctx, code.CodeInfo.Creator, code.CodesBytes, code.CodeInfo.Source, code.CodeInfo.Builder) if err != nil { panic(err) } diff --git a/x/wasm/internal/keeper/keeper.go b/x/wasm/internal/keeper/keeper.go index 7f274f6..d2d231f 100644 --- a/x/wasm/internal/keeper/keeper.go +++ b/x/wasm/internal/keeper/keeper.go @@ -62,7 +62,8 @@ func NewKeeper(cdc *codec.Codec, storeKey sdk.StoreKey, accountKeeper auth.Accou } // Create uploads and compiles a WASM contract, returning a short identifier for the contract -func (k Keeper) Create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte) (codeID uint64, sdkErr sdk.Error) { +func (k Keeper) Create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte, source string, + builder string) (codeID uint64, sdkErr sdk.Error) { wasmCode, err := uncompress(wasmCode) if err != nil { return 0, types.ErrCreateFailed(err) @@ -74,7 +75,7 @@ func (k Keeper) Create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte) store := ctx.KVStore(k.storeKey) codeID = k.autoIncrementID(ctx, types.KeyLastCodeID) - contractInfo := types.NewCodeInfo(codeHash, creator) + contractInfo := types.NewCodeInfo(codeHash, creator, source, builder) // 0x01 | codeID (uint64) -> ContractInfo store.Set(types.GetCodeKey(codeID), k.cdc.MustMarshalBinaryBare(contractInfo)) diff --git a/x/wasm/internal/keeper/keeper_test.go b/x/wasm/internal/keeper/keeper_test.go index 55d1006..f52de20 100644 --- a/x/wasm/internal/keeper/keeper_test.go +++ b/x/wasm/internal/keeper/keeper_test.go @@ -37,7 +37,7 @@ func TestCreate(t *testing.T) { wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm") require.NoError(t, err) - contractID, err := keeper.Create(ctx, creator, wasmCode) + contractID, err := keeper.Create(ctx, creator, wasmCode, "", "") require.NoError(t, err) require.Equal(t, uint64(1), contractID) // and verify content @@ -58,7 +58,7 @@ func TestCreateWithGzippedPayload(t *testing.T) { wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm.gzip") require.NoError(t, err) - contractID, err := keeper.Create(ctx, creator, wasmCode) + contractID, err := keeper.Create(ctx, creator, wasmCode, "", "") require.NoError(t, err) require.Equal(t, uint64(1), contractID) // and verify content @@ -81,7 +81,7 @@ func TestInstantiate(t *testing.T) { wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm") require.NoError(t, err) - contractID, err := keeper.Create(ctx, creator, wasmCode) + contractID, err := keeper.Create(ctx, creator, wasmCode, "", "") require.NoError(t, err) initMsg := InitMsg{ @@ -138,7 +138,7 @@ func TestExecute(t *testing.T) { wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm") require.NoError(t, err) - contractID, err := keeper.Create(ctx, creator, wasmCode) + contractID, err := keeper.Create(ctx, creator, wasmCode, "", "") require.NoError(t, err) _, _, bob := keyPubAddr() diff --git a/x/wasm/internal/keeper/querier_test.go b/x/wasm/internal/keeper/querier_test.go index eceb861..928e702 100644 --- a/x/wasm/internal/keeper/querier_test.go +++ b/x/wasm/internal/keeper/querier_test.go @@ -32,7 +32,7 @@ func TestQueryContractState(t *testing.T) { wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm") require.NoError(t, err) - contractID, err := keeper.Create(ctx, creator, wasmCode) + contractID, err := keeper.Create(ctx, creator, wasmCode, "", "") require.NoError(t, err) _, _, bob := keyPubAddr() diff --git a/x/wasm/internal/types/msg.go b/x/wasm/internal/types/msg.go index 939b8e7..8f1e9c9 100644 --- a/x/wasm/internal/types/msg.go +++ b/x/wasm/internal/types/msg.go @@ -12,6 +12,10 @@ type MsgStoreCode struct { Sender sdk.AccAddress `json:"sender" yaml:"sender"` // WASMByteCode can be raw or gzip compressed WASMByteCode []byte `json:"wasm_byte_code" yaml:"wasm_byte_code"` + // Source is a valid URI reference to the contract's source code, optional + Source string `json:"source" yaml:"source"` + // Builder is a docker tag, optional + Builder string `json:"builder" yaml:"builder"` } func (msg MsgStoreCode) Route() string { diff --git a/x/wasm/internal/types/types.go b/x/wasm/internal/types/types.go index 7e5ffe7..55df13e 100644 --- a/x/wasm/internal/types/types.go +++ b/x/wasm/internal/types/types.go @@ -16,13 +16,17 @@ type Model struct { type CodeInfo struct { CodeHash []byte `json:"code_hash"` Creator sdk.AccAddress `json:"creator"` + Source string `json:"source"` + Builder string `json:"builder"` } // NewCodeInfo fills a new Contract struct -func NewCodeInfo(codeHash []byte, creator sdk.AccAddress) CodeInfo { +func NewCodeInfo(codeHash []byte, creator sdk.AccAddress, source string, builder string) CodeInfo { return CodeInfo{ CodeHash: codeHash, Creator: creator, + Source: source, + Builder: builder, } }