From 40a24bad646d7ef6aa16fc79d9f458804b8c5453 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 2 Sep 2020 12:20:42 +0300 Subject: [PATCH] cli: add tests for `wallet import-deployed` Fix bugs with import, allow to sign tx with contract. --- cli/smartcontract/smart_contract.go | 4 +- cli/testdata/verify.go | 5 ++ cli/testdata/verify.manifest.json | 1 + cli/testdata/verify.nef | Bin 0 -> 82 bytes cli/wallet/wallet.go | 4 +- cli/wallet_test.go | 68 ++++++++++++++++++++++++++++ pkg/wallet/account.go | 4 ++ 7 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 cli/testdata/verify.go create mode 100755 cli/testdata/verify.manifest.json create mode 100755 cli/testdata/verify.nef diff --git a/cli/smartcontract/smart_contract.go b/cli/smartcontract/smart_contract.go index 5284630f5..f0b31b41d 100644 --- a/cli/smartcontract/smart_contract.go +++ b/cli/smartcontract/smart_contract.go @@ -681,7 +681,6 @@ func getAccFromContext(ctx *cli.Context) (*wallet.Account, error) { rawPass, err := input.ReadPassword(ctx.App.Writer, fmt.Sprintf("Enter account %s password > ", address.Uint160ToString(addr))) - fmt.Fprintln(ctx.App.Writer) if err != nil { return nil, cli.NewExitError(err, 1) } @@ -750,7 +749,8 @@ func contractDeploy(ctx *cli.Context) error { if err != nil { return cli.NewExitError(fmt.Errorf("failed to push invocation tx: %w", err), 1) } - fmt.Fprintf(ctx.App.Writer, "Sent deployment transaction %s for contract %s\n", txHash.StringLE(), nefFile.Header.ScriptHash.StringLE()) + fmt.Fprintf(ctx.App.Writer, "Contract: %s\n", nefFile.Header.ScriptHash.StringLE()) + fmt.Fprintln(ctx.App.Writer, txHash.StringLE()) return nil } diff --git a/cli/testdata/verify.go b/cli/testdata/verify.go new file mode 100644 index 000000000..467e1fd59 --- /dev/null +++ b/cli/testdata/verify.go @@ -0,0 +1,5 @@ +package testdata + +func Verify() bool { + return true +} diff --git a/cli/testdata/verify.manifest.json b/cli/testdata/verify.manifest.json new file mode 100755 index 000000000..970102f7c --- /dev/null +++ b/cli/testdata/verify.manifest.json @@ -0,0 +1 @@ +{"abi":{"hash":"0x8dff9f223e4622961f410c015dd37052a59892bb","methods":[{"name":"verify","offset":0,"parameters":[],"returntype":"Boolean"}],"events":[]},"groups":[],"features":{"payable":true,"storage":false},"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":[],"trusts":[],"safemethods":[],"extra":null} \ No newline at end of file diff --git a/cli/testdata/verify.nef b/cli/testdata/verify.nef new file mode 100755 index 0000000000000000000000000000000000000000..65f2011fb8ebd648989dcc76bfbb2734d495ed08 GIT binary patch literal 82 zcmeZsbu-RO&DTxOXTS@hfwGKH6}uBGcpJ| F007i?4%`3$ literal 0 HcmV?d00001 diff --git a/cli/wallet/wallet.go b/cli/wallet/wallet.go index c6e7ca55c..2b3c98532 100644 --- a/cli/wallet/wallet.go +++ b/cli/wallet/wallet.go @@ -407,7 +407,7 @@ func importDeployed(ctx *cli.Context) error { defer wall.Close() - rawHash := strings.TrimPrefix("0x", ctx.String("contract")) + rawHash := strings.TrimPrefix(ctx.String("contract"), "0x") h, err := util.Uint160DecodeStringLE(rawHash) if err != nil { return cli.NewExitError(fmt.Errorf("invalid contract hash: %w", err), 1) @@ -434,7 +434,9 @@ func importDeployed(ctx *cli.Context) error { if md == nil { return cli.NewExitError("contract has no `verify` method", 1) } + acc.Address = address.Uint160ToString(cs.ScriptHash()) acc.Contract.Script = cs.Script + acc.Contract.Parameters = acc.Contract.Parameters[:0] for _, p := range md.Parameters { acc.Contract.Parameters = append(acc.Contract.Parameters, wallet.ContractParam{ Name: p.Name, diff --git a/cli/wallet_test.go b/cli/wallet_test.go index 56edbf15a..8973eb7ad 100644 --- a/cli/wallet_test.go +++ b/cli/wallet_test.go @@ -10,7 +10,9 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "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/smartcontract" + "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/stretchr/testify/require" ) @@ -185,3 +187,69 @@ func TestClaimGas(t *testing.T) { balanceAfter := e.Chain.GetUtilityTokenBalance(validatorHash) require.Equal(t, 0, balanceAfter.Cmp(balanceBefore.Add(balanceBefore, cl))) } + +func TestImportDeployed(t *testing.T) { + e := newExecutor(t, true) + defer e.Close(t) + + e.In.WriteString("one\r") + e.Run(t, "neo-go", "contract", "deploy", + "--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr, + "--wallet", validatorWallet, "--address", validatorAddr, + "--in", "testdata/verify.nef", "--manifest", "testdata/verify.manifest.json") + + 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) + + tmpDir := os.TempDir() + walletPath := path.Join(tmpDir, "wallet.json") + e.Run(t, "neo-go", "wallet", "init", "--wallet", walletPath) + defer os.Remove(walletPath) + + priv, err := keys.NewPrivateKey() + require.NoError(t, err) + + e.In.WriteString("acc\rpass\rpass\r") + e.Run(t, "neo-go", "wallet", "import-deployed", + "--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr, + "--wallet", walletPath, "--wif", priv.WIF(), + "--contract", h.StringLE()) + + w, err := wallet.NewWalletFromFile(walletPath) + defer w.Close() + require.NoError(t, err) + require.Equal(t, 1, len(w.Accounts)) + contractAddr := w.Accounts[0].Address + require.Equal(t, address.Uint160ToString(h), contractAddr) + require.True(t, w.Accounts[0].Contract.Deployed) + + t.Run("Sign", func(t *testing.T) { + e.In.WriteString("one\r") + e.Run(t, "neo-go", "wallet", "nep5", "multitransfer", + "--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr, + "--wallet", validatorWallet, "--from", validatorAddr, + "neo:"+contractAddr+":10", + "gas:"+contractAddr+":10") + e.checkTxPersisted(t) + + privTo, err := keys.NewPrivateKey() + require.NoError(t, err) + + e.In.WriteString("pass\r") + e.Run(t, "neo-go", "wallet", "nep5", "transfer", + "--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr, + "--wallet", walletPath, "--from", contractAddr, + "--to", privTo.Address(), "--token", "neo", "--amount", "1") + e.checkTxPersisted(t) + + b, _ := e.Chain.GetGoverningTokenBalance(h) + require.Equal(t, big.NewInt(9), b) + b, _ = e.Chain.GetGoverningTokenBalance(privTo.GetScriptHash()) + require.Equal(t, big.NewInt(1), b) + }) +} diff --git a/pkg/wallet/account.go b/pkg/wallet/account.go index 393bf22a7..7b871759b 100644 --- a/pkg/wallet/account.go +++ b/pkg/wallet/account.go @@ -98,6 +98,10 @@ func (a *Account) SignTx(t *transaction.Transaction) error { if a.privateKey == nil { return errors.New("account is not unlocked") } + if len(a.Contract.Parameters) == 0 { + t.Scripts = append(t.Scripts, transaction.Witness{}) + return nil + } data := t.GetSignedPart() if data == nil { return errors.New("failed to get transaction's signed part")