Merge pull request #2213 from nspcc-dev/deploy-scope

cli/smartcontract: allow to deploy contracts with scope
This commit is contained in:
Roman Khimov 2021-10-13 16:02:09 +03:00 committed by GitHub
commit 40dfca3eda
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 102 additions and 38 deletions

View file

@ -164,6 +164,16 @@ func ParseParams(args []string, calledFromMain bool) (int, []smartcontract.Param
default: default:
param, err := smartcontract.NewParameterFromString(s) param, err := smartcontract.NewParameterFromString(s)
if err != nil { if err != nil {
// '--' argument is skipped by urfave/cli library, which leads
// to [--, addr:scope] being transformed to [addr:scope] and
// interpreted as a parameter if other positional arguments are not present.
// Here we fallback to parsing cosigners in this specific case to
// create a better user experience ('-- addr:scope' vs '-- -- addr:scope').
if k == 0 {
if _, err := parseCosigner(s); err == nil {
return 0, nil, nil
}
}
return 0, nil, fmt.Errorf("failed to parse argument #%d: %w", k+1, err) return 0, nil, fmt.Errorf("failed to parse argument #%d: %w", k+1, err)
} }
res = append(res, *param) res = append(res, *param)

View file

@ -14,6 +14,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/core/interop/storage" "github.com/nspcc-dev/neo-go/pkg/core/interop/storage"
"github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
@ -157,7 +158,7 @@ func TestDeployBigContract(t *testing.T) {
} }
func TestContractDeployWithData(t *testing.T) { func TestContractDeployWithData(t *testing.T) {
e := newExecutor(t, true) eCompile := newExecutor(t, false)
// For proper nef generation. // For proper nef generation.
config.Version = "0.90.0-test" config.Version = "0.90.0-test"
@ -165,20 +166,38 @@ func TestContractDeployWithData(t *testing.T) {
nefName := path.Join(tmpDir, "deploy.nef") nefName := path.Join(tmpDir, "deploy.nef")
manifestName := path.Join(tmpDir, "deploy.manifest.json") manifestName := path.Join(tmpDir, "deploy.manifest.json")
e.Run(t, "neo-go", "contract", "compile", eCompile.Run(t, "neo-go", "contract", "compile",
"--in", "testdata/deploy/main.go", // compile single file "--in", "testdata/deploy/main.go", // compile single file
"--config", "testdata/deploy/neo-go.yml", "--config", "testdata/deploy/neo-go.yml",
"--out", nefName, "--manifest", manifestName) "--out", nefName, "--manifest", manifestName)
e.In.WriteString("one\r") deployContract := func(t *testing.T, haveData bool, scope string) {
e.Run(t, "neo-go", "contract", "deploy", e := newExecutor(t, true)
"--rpc-endpoint", "http://"+e.RPC.Addr, cmd := []string{
"neo-go", "contract", "deploy",
"--rpc-endpoint", "http://" + e.RPC.Addr,
"--wallet", validatorWallet, "--address", validatorAddr, "--wallet", validatorWallet, "--address", validatorAddr,
"--in", nefName, "--manifest", manifestName, "--in", nefName, "--manifest", manifestName,
"--force", "--force",
"[", "key1", "12", "key2", "take_me_to_church", "]") }
if haveData {
cmd = append(cmd, "[", "key1", "12", "key2", "take_me_to_church", "]")
}
if scope != "" {
cmd = append(cmd, "--", validatorAddr+":"+scope)
} else {
scope = "CalledByEntry"
}
e.In.WriteString("one\r")
e.Run(t, cmd...)
tx, _ := e.checkTxPersisted(t, "Sent invocation transaction ")
require.Equal(t, scope, tx.Signers[0].Scopes.String())
if !haveData {
return
}
e.checkTxPersisted(t, "Sent invocation transaction ")
line, err := e.Out.ReadString('\n') line, err := e.Out.ReadString('\n')
require.NoError(t, err) require.NoError(t, err)
line = strings.TrimSpace(strings.TrimPrefix(line, "Contract: ")) line = strings.TrimSpace(strings.TrimPrefix(line, "Contract: "))
@ -208,6 +227,36 @@ func TestContractDeployWithData(t *testing.T) {
require.Equal(t, vm.HaltState.String(), res.State, res.FaultException) require.Equal(t, vm.HaltState.String(), res.State, res.FaultException)
require.Len(t, res.Stack, 1) require.Len(t, res.Stack, 1)
require.Equal(t, []byte("take_me_to_church"), res.Stack[0].Value()) require.Equal(t, []byte("take_me_to_church"), res.Stack[0].Value())
}
deployContract(t, true, "")
deployContract(t, false, "Global")
deployContract(t, true, "Global")
}
func TestDeployWithSigners(t *testing.T) {
e := newExecutor(t, true)
// For proper nef generation.
config.Version = "0.90.0-test"
tmpDir := t.TempDir()
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",
"--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,
"--force",
"--", validatorAddr+":Global")
tx, _ := e.checkTxPersisted(t, "Sent invocation transaction ")
require.Equal(t, transaction.Global, tx.Signers[0].Scopes)
} }
func TestContractManifestGroups(t *testing.T) { func TestContractManifestGroups(t *testing.T) {

View file

@ -843,7 +843,7 @@ func contractDeploy(ctx *cli.Context) error {
Value: manifestBytes, Value: manifestBytes,
}, },
} }
_, data, err := cmdargs.ParseParams(ctx.Args(), true) signOffset, data, err := cmdargs.ParseParams(ctx.Args(), true)
if err != nil { if err != nil {
return cli.NewExitError(fmt.Errorf("unable to parse 'data' parameter: %w", err), 1) return cli.NewExitError(fmt.Errorf("unable to parse 'data' parameter: %w", err), 1)
} }
@ -872,10 +872,15 @@ func contractDeploy(ctx *cli.Context) error {
return cli.NewExitError(fmt.Errorf("can't get sender address: %w", err), 1) return cli.NewExitError(fmt.Errorf("can't get sender address: %w", err), 1)
} }
cosigners := []transaction.Signer{{ cosigners, sgnErr := cmdargs.GetSignersFromContext(ctx, signOffset)
if sgnErr != nil {
return err
} else if len(cosigners) == 0 {
cosigners = []transaction.Signer{{
Account: acc.Contract.ScriptHash(), Account: acc.Contract.ScriptHash(),
Scopes: transaction.CalledByEntry, Scopes: transaction.CalledByEntry,
}} }}
}
sender, extErr := invokeWithArgs(ctx, acc, w, mgmtHash, "deploy", appCallParams, cosigners) sender, extErr := invokeWithArgs(ctx, acc, w, mgmtHash, "deploy", appCallParams, cosigners)
if extErr != nil { if extErr != nil {