diff --git a/cli/contract_test.go b/cli/contract_test.go index f83d3c073..fffcb2d85 100644 --- a/cli/contract_test.go +++ b/cli/contract_test.go @@ -168,6 +168,64 @@ func TestDeployBigContract(t *testing.T) { "--in", nefName, "--manifest", manifestName) } +func TestContractDeployWithData(t *testing.T) { + e := newExecutor(t, true) + + // For proper nef generation. + config.Version = "0.90.0-test" + + tmpDir := path.Join(os.TempDir(), "neogo.test.deployfail") + require.NoError(t, os.Mkdir(tmpDir, os.ModePerm)) + t.Cleanup(func() { + os.RemoveAll(tmpDir) + }) + + nefName := path.Join(tmpDir, "deploy.nef") + manifestName := path.Join(tmpDir, "deploy.manifest.json") + e.Run(t, "neo-go", "contract", "compile", + "--in", "testdata/deploy/main.go", // compile single file + "--config", "testdata/deploy/neo-go.yml", + "--out", nefName, "--manifest", manifestName) + + e.In.WriteString("one\r") + e.Run(t, "neo-go", "contract", "deploy", + "--rpc-endpoint", "http://"+e.RPC.Addr, + "--wallet", validatorWallet, "--address", validatorAddr, + "--in", nefName, "--manifest", manifestName, + "[", "key1", "12", "key2", "take_me_to_church", "]") + + line, err := e.Out.ReadString('\n') + require.NoError(t, err) + line = strings.TrimSpace(strings.TrimPrefix(line, "Contract: ")) + h, err := util.Uint160DecodeStringLE(line) + require.NoError(t, err) + e.checkTxPersisted(t) + + e.Run(t, "neo-go", "contract", "testinvokefunction", + "--rpc-endpoint", "http://"+e.RPC.Addr, + h.StringLE(), + "getValueWithKey", "key1", + ) + + res := new(result.Invoke) + require.NoError(t, json.Unmarshal(e.Out.Bytes(), res)) + require.Equal(t, vm.HaltState.String(), res.State, res.FaultException) + require.Len(t, res.Stack, 1) + require.Equal(t, []byte{12}, res.Stack[0].Value()) + + e.Run(t, "neo-go", "contract", "testinvokefunction", + "--rpc-endpoint", "http://"+e.RPC.Addr, + h.StringLE(), + "getValueWithKey", "key2", + ) + + res = new(result.Invoke) + require.NoError(t, json.Unmarshal(e.Out.Bytes(), res)) + require.Equal(t, vm.HaltState.String(), res.State, res.FaultException) + require.Len(t, res.Stack, 1) + require.Equal(t, []byte("take_me_to_church"), res.Stack[0].Value()) +} + func TestComlileAndInvokeFunction(t *testing.T) { e := newExecutor(t, true) diff --git a/cli/smartcontract/smart_contract.go b/cli/smartcontract/smart_contract.go index d7f7224fb..ccf723b79 100644 --- a/cli/smartcontract/smart_contract.go +++ b/cli/smartcontract/smart_contract.go @@ -169,10 +169,12 @@ func NewCommands() []cli.Command { }, }, { - Name: "deploy", - Usage: "deploy a smart contract (.nef with description)", + Name: "deploy", + Usage: "deploy a smart contract (.nef with description)", + UsageText: "neo-go contract deploy -r endpoint -w wallet [-a address] [-g gas] --in contract.nef --manifest contract.manifest.json [--out file] [data]", Description: `Deploys given contract into the chain. The gas parameter is for additional - gas to be added as a network fee to prioritize the transaction. + gas to be added as a network fee to prioritize the transaction. The data + parameter is an optional parameter to be passed to '_deploy' method. `, Action: contractDeploy, Flags: deployFlags, @@ -836,6 +838,15 @@ func contractDeploy(ctx *cli.Context) error { return cli.NewExitError(fmt.Errorf("failed to restore manifest file: %w", err), 1) } + data, extErr := GetDataFromContext(ctx) + if extErr != nil { + return extErr + } + appCallParams := []interface{}{f, manifestBytes} + if data != nil { + appCallParams = append(appCallParams, data) + } + gctx, cancel := options.GetTimeoutContext(ctx) defer cancel() @@ -851,7 +862,7 @@ func contractDeploy(ctx *cli.Context) error { buf := io.NewBufBinWriter() emit.AppCall(buf.BinWriter, mgmtHash, "deploy", callflag.ReadStates|callflag.WriteStates|callflag.AllowNotify, - f, manifestBytes) + appCallParams...) if buf.Err != nil { return cli.NewExitError(fmt.Errorf("failed to create deployment script: %w", buf.Err), 1) } diff --git a/cli/testdata/deploy/main.go b/cli/testdata/deploy/main.go index 8a181dc77..88a3d0f67 100644 --- a/cli/testdata/deploy/main.go +++ b/cli/testdata/deploy/main.go @@ -23,6 +23,13 @@ func _deploy(data interface{}, isUpdate bool) { value = "on create" sh := runtime.GetCallingScriptHash() storage.Put(ctx, mgmtKey, sh) + + if data != nil { + arr := data.([]interface{}) + for i := 0; i < len(arr)-1; i += 2 { + storage.Put(ctx, arr[i], arr[i+1]) + } + } } storage.Put(ctx, key, value) @@ -48,6 +55,12 @@ func GetValue() string { return val1.(string) + "|" + val2.(string) } +// GetValueWithKey returns stored value with the specified key. +func GetValueWithKey(key string) string { + ctx := storage.GetReadOnlyContext() + return storage.Get(ctx, key).(string) +} + // TestFind finds items with the specified prefix. func TestFind(f storage.FindFlags) []interface{} { ctx := storage.GetContext()