Merge pull request #1590 from nspcc-dev/tests/wallet

Add CLI tests for `contract` and `wallet` commands
This commit is contained in:
Roman Khimov 2020-12-04 16:16:23 +03:00 committed by GitHub
commit 818dc078da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 586 additions and 86 deletions

View file

@ -16,6 +16,61 @@ import (
"github.com/stretchr/testify/require"
)
func TestContractInitAndCompile(t *testing.T) {
tmpDir := path.Join(os.TempDir(), "neogo.inittest")
require.NoError(t, os.Mkdir(tmpDir, os.ModePerm))
defer os.RemoveAll(tmpDir)
e := newExecutor(t, false)
defer e.Close(t)
t.Run("no path is provided", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "init")
})
t.Run("invalid path", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "init", "--name", "\x00")
})
ctrPath := path.Join(tmpDir, "testcontract")
e.Run(t, "neo-go", "contract", "init", "--name", ctrPath)
t.Run("don't rewrite existing directory", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "init", "--name", ctrPath)
})
// For proper nef generation.
config.Version = "0.90.0-test"
srcPath := path.Join(ctrPath, "main.go")
cfgPath := path.Join(ctrPath, "neo-go.yml")
nefPath := path.Join(tmpDir, "testcontract.nef")
manifestPath := path.Join(tmpDir, "testcontract.manifest.json")
cmd := []string{"neo-go", "contract", "compile"}
t.Run("missing source", func(t *testing.T) {
e.RunWithError(t, cmd...)
})
cmd = append(cmd, "--in", srcPath, "--out", nefPath, "--manifest", manifestPath)
t.Run("missing config, but require manifest", func(t *testing.T) {
e.RunWithError(t, cmd...)
})
t.Run("provided non-existent config", func(t *testing.T) {
cfgName := path.Join(ctrPath, "notexists.yml")
e.RunWithError(t, append(cmd, "--config", cfgName)...)
})
cmd = append(cmd, "--config", cfgPath)
e.Run(t, cmd...)
e.checkEOF(t)
require.FileExists(t, nefPath)
require.FileExists(t, manifestPath)
t.Run("output hex script with --verbose", func(t *testing.T) {
e.Run(t, append(cmd, "--verbose")...)
e.checkNextLine(t, "^[0-9a-hA-H]+$")
})
}
func TestComlileAndInvokeFunction(t *testing.T) {
e := newExecutor(t, true)
defer e.Close(t)
@ -23,7 +78,10 @@ func TestComlileAndInvokeFunction(t *testing.T) {
// For proper nef generation.
config.Version = "0.90.0-test"
tmpDir := os.TempDir()
tmpDir := path.Join(os.TempDir(), "neogo.test.compileandinvoke")
require.NoError(t, os.Mkdir(tmpDir, os.ModePerm))
defer os.RemoveAll(tmpDir)
nefName := path.Join(tmpDir, "deploy.nef")
manifestName := path.Join(tmpDir, "deploy.manifest.json")
e.Run(t, "neo-go", "contract", "compile",
@ -31,10 +89,12 @@ func TestComlileAndInvokeFunction(t *testing.T) {
"--config", "testdata/deploy/neo-go.yml",
"--out", nefName, "--manifest", manifestName)
defer func() {
os.Remove(nefName)
os.Remove(manifestName)
}()
// Check that it is possible to invoke before deploy.
// This doesn't make much sense, because every method has an offset
// which is contained in the manifest. This should be either removed or refactored.
e.Run(t, "neo-go", "contract", "testinvokescript",
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--in", nefName, "--", util.Uint160{1, 2, 3}.StringLE())
e.In.WriteString("one\r")
e.Run(t, "neo-go", "contract", "deploy",
@ -49,10 +109,33 @@ func TestComlileAndInvokeFunction(t *testing.T) {
require.NoError(t, err)
e.checkTxPersisted(t)
e.In.WriteString("one\r")
e.Run(t, "neo-go", "contract", "testinvokefunction",
"--rpc-endpoint", "http://"+e.RPC.Addr,
h.StringLE(), "getValue")
cmd := []string{"neo-go", "contract", "testinvokefunction",
"--rpc-endpoint", "http://" + e.RPC.Addr}
t.Run("missing hash", func(t *testing.T) {
e.RunWithError(t, cmd...)
})
t.Run("invalid hash", func(t *testing.T) {
e.RunWithError(t, append(cmd, "notahash")...)
})
cmd = append(cmd, h.StringLE())
t.Run("missing method", func(t *testing.T) {
e.RunWithError(t, cmd...)
})
cmd = append(cmd, "getValue")
t.Run("invalid params", func(t *testing.T) {
e.RunWithError(t, append(cmd, "[")...)
})
t.Run("invalid cosigner", func(t *testing.T) {
e.RunWithError(t, append(cmd, "--", "notahash")...)
})
t.Run("missing RPC address", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "testinvokefunction",
h.StringLE(), "getValue")
})
e.Run(t, cmd...)
res := new(result.Invoke)
require.NoError(t, json.Unmarshal(e.Out.Bytes(), res))
@ -60,6 +143,32 @@ func TestComlileAndInvokeFunction(t *testing.T) {
require.Len(t, res.Stack, 1)
require.Equal(t, []byte("on create|sub create"), res.Stack[0].Value())
t.Run("real invoke", func(t *testing.T) {
cmd := []string{"neo-go", "contract", "invokefunction",
"--rpc-endpoint", "http://" + e.RPC.Addr}
t.Run("missing wallet", func(t *testing.T) {
cmd := append(cmd, h.StringLE(), "getValue")
e.RunWithError(t, cmd...)
})
t.Run("non-existent wallet", func(t *testing.T) {
cmd := append(cmd, "--wallet", path.Join(tmpDir, "not.exists"),
h.StringLE(), "getValue")
e.RunWithError(t, cmd...)
})
cmd = append(cmd, "--wallet", validatorWallet, "--address", validatorAddr)
e.In.WriteString("one\r")
e.Run(t, append(cmd, h.StringLE(), "getValue")...)
t.Run("failind method", func(t *testing.T) {
e.In.WriteString("one\r")
e.RunWithError(t, append(cmd, h.StringLE(), "fail")...)
e.In.WriteString("one\r")
e.Run(t, append(cmd, "--force", h.StringLE(), "fail")...)
})
})
t.Run("Update", func(t *testing.T) {
nefName := path.Join(tmpDir, "updated.nef")
manifestName := path.Join(tmpDir, "updated.manifest.json")
@ -101,6 +210,42 @@ func TestComlileAndInvokeFunction(t *testing.T) {
})
}
func TestContractInspect(t *testing.T) {
e := newExecutor(t, false)
defer e.Close(t)
// For proper nef generation.
config.Version = "0.90.0-test"
const srcPath = "testdata/deploy/main.go"
tmpDir := path.Join(os.TempDir(), "neogo.test.contract.inspect")
require.NoError(t, os.Mkdir(tmpDir, os.ModePerm))
defer os.RemoveAll(tmpDir)
nefName := path.Join(tmpDir, "deploy.nef")
manifestName := path.Join(tmpDir, "deploy.manifest.json")
e.Run(t, "neo-go", "contract", "compile",
"--in", srcPath,
"--config", "testdata/deploy/neo-go.yml",
"--out", nefName, "--manifest", manifestName)
cmd := []string{"neo-go", "contract", "inspect"}
t.Run("missing input", func(t *testing.T) {
e.RunWithError(t, cmd...)
})
t.Run("with raw '.go'", func(t *testing.T) {
e.RunWithError(t, append(cmd, "--in", srcPath)...)
e.Run(t, append(cmd, "--in", srcPath, "--compile")...)
require.True(t, strings.Contains(e.Out.String(), "SYSCALL"))
})
t.Run("with nef", func(t *testing.T) {
e.RunWithError(t, append(cmd, "--in", nefName, "--compile")...)
e.RunWithError(t, append(cmd, "--in", path.Join(tmpDir, "not.exists"))...)
e.Run(t, append(cmd, "--in", nefName)...)
require.True(t, strings.Contains(e.Out.String(), "SYSCALL"))
})
}
func TestCompileExamples(t *testing.T) {
const examplePath = "../examples"
infos, err := ioutil.ReadDir(examplePath)

View file

@ -132,7 +132,7 @@ func (e *executor) GetTransaction(t *testing.T, h util.Uint256) (*transaction.Tr
func (e *executor) getNextLine(t *testing.T) string {
line, err := e.Out.ReadString('\n')
require.NoError(t, err)
return line
return strings.TrimSuffix(line, "\n")
}
func (e *executor) checkNextLine(t *testing.T, expected string) {
@ -184,7 +184,9 @@ func (e *executor) Run(t *testing.T, args ...string) {
func (e *executor) run(args ...string) error {
e.Out.Reset()
e.Err.Reset()
return e.CLI.Run(args)
err := e.CLI.Run(args)
e.In.Reset()
return err
}
func (e *executor) checkTxPersisted(t *testing.T, prefix ...string) (*transaction.Transaction, uint32) {

View file

@ -36,8 +36,8 @@ func TestSignMultisigTx(t *testing.T) {
defer os.Remove(wallet2Path)
addAccount := func(w string, wif string) {
e.In.WriteString("acc\rpass\rpass\r")
e.Run(t, "neo-go", "wallet", "init", "--wallet", w)
e.In.WriteString("acc\rpass\rpass\r")
e.Run(t, "neo-go", "wallet", "import-multisig",
"--wallet", w,
"--wif", wif,

View file

@ -295,17 +295,6 @@ func restoreDB(ctx *cli.Context) error {
return nil
}
// readBlock performs reading of block size and then bytes with the length equal to that size.
func readBlock(reader *io.BinReader) ([]byte, error) {
var size = reader.ReadU32LE()
bytes := make([]byte, size)
reader.ReadBytes(bytes)
if reader.Err != nil {
return nil, reader.Err
}
return bytes, nil
}
func startServer(ctx *cli.Context) error {
cfg, err := getConfigFromContext(ctx)
if err != nil {

View file

@ -7,6 +7,7 @@ import (
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"strings"
@ -56,7 +57,7 @@ var (
Name: "out",
Usage: "file to put JSON transaction to",
}
forceFlag = cli.StringFlag{
forceFlag = cli.BoolFlag{
Name: "force",
Usage: "force-push the transaction in case of bad VM state after test script invocation",
}
@ -350,6 +351,7 @@ func initSmartContract(ctx *cli.Context) error {
}
basePath := contractName
contractName = path.Base(contractName)
fileName := "main.go"
// create base directory
@ -500,9 +502,6 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
if err != nil {
return err
}
if err = c.Init(); err != nil {
return err
}
resp, err = c.InvokeFunction(script, operation, params, cosigners)
if err != nil {
@ -510,7 +509,7 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
}
if signAndPush && resp.State != "HALT" {
errText := fmt.Sprintf("Warning: %s VM state returned from the RPC node: %s\n", resp.State, resp.FaultException)
if ctx.String("force") == "" {
if !ctx.Bool("force") {
return cli.NewExitError(errText+". Use --force flag to send the transaction anyway.", 1)
}
fmt.Fprintln(ctx.App.Writer, errText+". Sending transaction...")

View file

@ -17,6 +17,11 @@ func _deploy(isUpdate bool) {
storage.Put(ctx, key, value)
}
// Fail just fails.
func Fail() {
panic("as expected")
}
// Update updates contract with the new one.
func Update(script, manifest []byte) {
contract.Update(script, manifest)

View file

@ -0,0 +1 @@
{"name":"wallet1","version":"1.0","scrypt":{"n":16384,"r":8,"p":8},"accounts":[{"address":"AKkkumHbBipZ46UMZJoFynJMXzSRnBvKcs","label":null,"isDefault":false,"lock":false,"key":"6PYLmjBYJ4wQTCEfqvnznGJwZeW9pfUcV5m5oreHxqryUgqKpTRAFt9L8Y","contract":{"script":"2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2ac","parameters":[{"name":"parameter0","type":"Signature"}],"deployed":false},"extra":null},{"address":"AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU","label":null,"isDefault":false,"lock":false,"key":"6PYLmjBYJ4wQTCEfqvnznGJwZeW9pfUcV5m5oreHxqryUgqKpTRAFt9L8Y","contract":{"script":"532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae","parameters":[{"name":"parameter0","type":"Signature"},{"name":"parameter1","type":"Signature"},{"name":"parameter2","type":"Signature"}],"deployed":false},"extra":null}],"extra":null}

View file

@ -0,0 +1,55 @@
{
"version": "3.0",
"accounts": [
{
"address": "NbTiM6h8r99kpRtb428XcsUk1TzKed2gTc",
"key": "6PYN7LvaWqBNw7Xb7a52LSbPnP91kyuzYi3HncGvQwQoYAY2W8DncTgpux",
"label": "",
"contract": {
"script": "DCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcILQZVEDXg=",
"parameters": [
{
"name": "parameter0",
"type": "Signature"
}
],
"deployed": false
},
"lock": false,
"isdefault": false
},
{
"address": "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"key": "6PYN7LvaWqBNw7Xb7a52LSbPnP91kyuzYi3HncGvQwQoYAY2W8DncTgpux",
"label": "",
"contract": {
"script": "EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFAtBE43vrw==",
"parameters": [
{
"name": "parameter0",
"type": "Signature"
},
{
"name": "parameter1",
"type": "Signature"
},
{
"name": "parameter2",
"type": "Signature"
}
],
"deployed": false
},
"lock": false,
"isdefault": false
}
],
"scrypt": {
"n": 16384,
"r": 8,
"p": 8
},
"extra": {
"Tokens": null
}
}

162
cli/wallet/legacy.go Normal file
View file

@ -0,0 +1,162 @@
package wallet
import (
"crypto/elliptic"
"encoding/binary"
"encoding/hex"
"encoding/json"
"errors"
"os"
"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/wallet"
)
type (
walletV2 struct {
Version string `json:"version"`
Accounts []accountV2 `json:"accounts"`
Scrypt keys.ScryptParams `json:"scrypt"`
Extra wallet.Extra `json:"extra"`
}
accountV2 struct {
Address string `json:"address"`
EncryptedWIF string `json:"key"`
Label string `json:"label"`
Contract *struct {
Script string `json:"script"`
Parameters []wallet.ContractParam `json:"parameters"`
Deployed bool `json:"deployed"`
} `json:"contract"`
Locked bool `json:"lock"`
Default bool `json:"isdefault"`
}
)
// newWalletV2FromFile reads NEO2 wallet from file.
// This should be used read-only, no operations are supported on returned wallet.
func newWalletV2FromFile(path string) (*walletV2, error) {
file, err := os.OpenFile(path, os.O_RDWR, os.ModeAppend)
if err != nil {
return nil, err
}
defer file.Close()
wall := new(walletV2)
return wall, json.NewDecoder(file).Decode(wall)
}
const simpleSigLen = 35
func (a *accountV2) convert(pass string) (*wallet.Account, error) {
address.Prefix = address.NEO2Prefix
priv, err := keys.NEP2Decrypt(a.EncryptedWIF, pass)
if err != nil {
return nil, err
}
address.Prefix = address.NEO3Prefix
newAcc := wallet.NewAccountFromPrivateKey(priv)
if a.Contract != nil {
script, err := hex.DecodeString(a.Contract.Script)
if err != nil {
return nil, err
}
// If it is simple signature script, newAcc does already have it.
if len(script) != simpleSigLen {
nsigs, pubs, ok := parseMultisigContract(script)
if !ok {
return nil, errors.New("invalid multisig contract")
}
script, err := smartcontract.CreateMultiSigRedeemScript(nsigs, pubs)
if err != nil {
return nil, errors.New("can't create new multisig contract")
}
newAcc.Contract.Script = script
newAcc.Contract.Parameters = a.Contract.Parameters
newAcc.Contract.Deployed = a.Contract.Deployed
}
}
newAcc.Address = address.Uint160ToString(newAcc.Contract.ScriptHash())
newAcc.Default = a.Default
newAcc.Label = a.Label
newAcc.Locked = a.Locked
return newAcc, newAcc.Encrypt(pass)
}
const (
opPush1 = 0x51
opPush16 = 0x60
opPushBytes1 = 0x01
opPushBytes2 = 0x02
opPushBytes33 = 0x21
opCheckMultisig = 0xAE
opRet = 0x66
)
func getNumOfThingsFromInstr(script []byte) (int, int, bool) {
var op = script[0]
switch {
case opPush1 <= op && op <= opPush16:
return int(op-opPush1) + 1, 1, true
case op == opPushBytes1 && len(script) >= 2:
return int(script[1]), 2, true
case op == opPushBytes2 && len(script) >= 3:
return int(binary.LittleEndian.Uint16(script[1:])), 3, true
default:
return 0, 0, false
}
}
const minMultisigLen = 37
// parseMultisigContract accepts multisig verification script from NEO2
// and returns list of public keys in the same order as in script..
func parseMultisigContract(script []byte) (int, keys.PublicKeys, bool) {
// It should contain at least 1 public key.
if len(script) < minMultisigLen {
return 0, nil, false
}
nsigs, offset, ok := getNumOfThingsFromInstr(script)
if !ok {
return 0, nil, false
}
var pubs [][]byte
var nkeys int
for offset < len(script) && script[offset] == opPushBytes33 {
if len(script[offset:]) < 34 {
return 0, nil, false
}
pubs = append(pubs, script[offset+1:offset+34])
nkeys++
offset += 34
}
if nkeys < nsigs || offset >= len(script) {
return 0, nil, false
}
nkeys2, off, ok := getNumOfThingsFromInstr(script[offset:])
if !ok || nkeys2 != nkeys {
return 0, nil, false
}
end := script[offset+off:]
switch {
case len(end) == 1 && end[0] == opCheckMultisig:
case len(end) == 2 && end[0] == opCheckMultisig && end[1] == opRet:
default:
return 0, nil, false
}
ret := make(keys.PublicKeys, len(pubs))
for i := range pubs {
pub, err := keys.NewPublicKeyFromBytes(pubs[i], elliptic.P256())
if err != nil {
return 0, nil, false
}
ret[i] = pub
}
return nsigs, ret, true
}

111
cli/wallet/legacy_test.go Normal file
View file

@ -0,0 +1,111 @@
package wallet
import (
"crypto/elliptic"
"encoding/hex"
"testing"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/stretchr/testify/require"
)
func testParseMultisigContract(t *testing.T, s []byte, nsigs int, keys ...*keys.PublicKey) {
ns, ks, ok := parseMultisigContract(s)
if len(keys) == 0 {
require.False(t, ok)
return
}
require.True(t, ok)
require.Equal(t, nsigs, ns)
require.Equal(t, len(keys), len(ks))
for i := range keys {
require.Equal(t, keys[i], ks[i])
}
}
func TestParseMultisigContract(t *testing.T) {
t.Run("single multisig", func(t *testing.T) {
s := fromHex(t, "512102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc251ae")
pub := pubFromHex(t, "02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2")
t.Run("good, no ret", func(t *testing.T) {
testParseMultisigContract(t, s, 1, pub)
})
t.Run("good, with ret", func(t *testing.T) {
s := append(s, opRet)
testParseMultisigContract(t, s, 1, pub)
})
t.Run("bad, no check multisig", func(t *testing.T) {
sBad := make([]byte, len(s))
copy(sBad, s)
sBad[len(sBad)-1] ^= 0xFF
testParseMultisigContract(t, sBad, 0)
})
t.Run("bad, invalid number of keys", func(t *testing.T) {
sBad := make([]byte, len(s))
copy(sBad, s)
sBad[len(sBad)-2] = opPush1 + 1
testParseMultisigContract(t, sBad, 0)
})
t.Run("bad, invalid first instruction", func(t *testing.T) {
sBad := make([]byte, len(s))
copy(sBad, s)
sBad[0] = 0xFF
testParseMultisigContract(t, sBad, 0)
})
t.Run("bad, invalid public key", func(t *testing.T) {
sBad := make([]byte, len(s))
copy(sBad, s)
sBad[2] = 0xFF
testParseMultisigContract(t, sBad, 0)
})
t.Run("bad, many sigs", func(t *testing.T) {
sBad := make([]byte, len(s))
copy(sBad, s)
sBad[0] = opPush1 + 1
testParseMultisigContract(t, sBad, 0)
})
t.Run("empty, no panic", func(t *testing.T) {
testParseMultisigContract(t, []byte{}, 0)
})
})
t.Run("3/4 multisig", func(t *testing.T) {
// From privnet consensus wallet.
s := fromHex(t, "532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae")
ks := keys.PublicKeys{
pubFromHex(t, "02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e"),
pubFromHex(t, "02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62"),
pubFromHex(t, "02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2"),
pubFromHex(t, "03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699"),
}
t.Run("good", func(t *testing.T) {
testParseMultisigContract(t, s, 3, ks...)
})
t.Run("good, with pushbytes1", func(t *testing.T) {
s := append([]byte{opPushBytes1, 3}, s[1:]...)
testParseMultisigContract(t, s, 3, ks...)
})
t.Run("good, with pushbytes2", func(t *testing.T) {
s := append([]byte{opPushBytes2, 3, 0}, s[1:]...)
testParseMultisigContract(t, s, 3, ks...)
})
t.Run("bad, no panic on prefix", func(t *testing.T) {
for i := minMultisigLen; i < len(s)-1; i++ {
testParseMultisigContract(t, s[:i], 0)
}
})
})
}
func fromHex(t *testing.T, s string) []byte {
bs, err := hex.DecodeString(s)
require.NoError(t, err)
return bs
}
func pubFromHex(t *testing.T, s string) *keys.PublicKey {
bs := fromHex(t, s)
pub, err := keys.NewPublicKeyFromBytes(bs, elliptic.P256())
require.NoError(t, err)
return pub
}

View file

@ -158,10 +158,6 @@ func getNEP17Balance(ctx *cli.Context) error {
if err != nil {
return cli.NewExitError(err, 1)
}
err = c.Init()
if err != nil {
return cli.NewExitError(fmt.Errorf("failed to init RPC client: %w", err), 1)
}
name := ctx.String("token")
@ -366,10 +362,6 @@ func multiTransferNEP17(ctx *cli.Context) error {
if err != nil {
return cli.NewExitError(err, 1)
}
err = c.Init()
if err != nil {
return cli.NewExitError(fmt.Errorf("failed to init RPC client: %w", err), 1)
}
if ctx.NArg() == 0 {
return cli.NewExitError("empty recipients list", 1)
@ -433,10 +425,6 @@ func transferNEP17(ctx *cli.Context) error {
if err != nil {
return cli.NewExitError(err, 1)
}
err = c.Init()
if err != nil {
return cli.NewExitError(fmt.Errorf("failed to init RPC client: %w", err), 1)
}
toFlag := ctx.Generic("to").(*flags.Address)
to := toFlag.Uint160()

View file

@ -247,40 +247,25 @@ func claimGas(ctx *cli.Context) error {
}
func convertWallet(ctx *cli.Context) error {
wall, err := openWallet(ctx.String("wallet"))
wall, err := newWalletV2FromFile(ctx.String("wallet"))
if err != nil {
return cli.NewExitError(err, 1)
}
defer wall.Close()
newWallet, err := wallet.NewWallet(ctx.String("out"))
if err != nil {
return cli.NewExitError(err, -1)
return cli.NewExitError(err, 1)
}
defer newWallet.Close()
for _, acc := range wall.Accounts {
address.Prefix = address.NEO2Prefix
pass, err := input.ReadPassword(ctx.App.Writer, fmt.Sprintf("Enter passphrase for account %s (label '%s') > ", acc.Address, acc.Label))
if err != nil {
return cli.NewExitError(err, -1)
} else if err := acc.Decrypt(pass); err != nil {
return cli.NewExitError("invalid passphrase", -1)
return cli.NewExitError(err, 1)
}
address.Prefix = address.NEO3Prefix
newAcc, err := wallet.NewAccountFromWIF(acc.PrivateKey().WIF())
newAcc, err := acc.convert(pass)
if err != nil {
return cli.NewExitError(fmt.Errorf("can't convert account: %w", err), -1)
}
newAcc.Address = address.Uint160ToString(acc.Contract.ScriptHash())
newAcc.Contract = acc.Contract
newAcc.Default = acc.Default
newAcc.Label = acc.Label
newAcc.Locked = acc.Locked
if err := newAcc.Encrypt(pass); err != nil {
return cli.NewExitError(fmt.Errorf("can't encrypt converted account: %w", err), -1)
return cli.NewExitError(err, 1)
}
newWallet.AddAccount(newAcc)
}

View file

@ -286,10 +286,73 @@ func TestWalletDump(t *testing.T) {
e := newExecutor(t, false)
defer e.Close(t)
e.Run(t, "neo-go", "wallet", "dump", "--wallet", "testdata/testwallet.json")
cmd := []string{"neo-go", "wallet", "dump", "--wallet", "testdata/testwallet.json"}
e.Run(t, cmd...)
rawStr := strings.TrimSpace(e.Out.String())
w := new(wallet.Wallet)
require.NoError(t, json.Unmarshal([]byte(rawStr), w))
require.Equal(t, 1, len(w.Accounts))
require.Equal(t, "NNuJqXDnRqvwgzhSzhH4jnVFWB1DyZ34EM", w.Accounts[0].Address)
t.Run("with decrypt", func(t *testing.T) {
cmd = append(cmd, "--decrypt")
t.Run("invalid password", func(t *testing.T) {
e.In.WriteString("invalidpass\r")
e.RunWithError(t, cmd...)
})
e.In.WriteString("testpass\r")
e.Run(t, cmd...)
rawStr := strings.TrimSpace(e.Out.String())
w := new(wallet.Wallet)
require.NoError(t, json.Unmarshal([]byte(rawStr), w))
require.Equal(t, 1, len(w.Accounts))
require.Equal(t, "NNuJqXDnRqvwgzhSzhH4jnVFWB1DyZ34EM", w.Accounts[0].Address)
})
}
// Testcase is the wallet of privnet validator.
func TestWalletConvert(t *testing.T) {
tmpDir := path.Join(os.TempDir(), "neogo.test.convert")
require.NoError(t, os.Mkdir(tmpDir, os.ModePerm))
defer os.RemoveAll(tmpDir)
e := newExecutor(t, false)
defer e.Close(t)
outPath := path.Join(tmpDir, "wallet.json")
cmd := []string{"neo-go", "wallet", "convert"}
t.Run("missing wallet", func(t *testing.T) {
e.RunWithError(t, cmd...)
})
cmd = append(cmd, "--wallet", "testdata/wallets/testwallet_NEO2.json", "--out", outPath)
t.Run("invalid password", func(t *testing.T) {
// missing password
e.RunWithError(t, cmd...)
// invalid password
e.In.WriteString("two\r")
e.RunWithError(t, cmd...)
})
// 2 accounts.
e.In.WriteString("one\r")
e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "convert",
"--wallet", "testdata/wallets/testwallet_NEO2.json",
"--out", outPath)
actual, err := wallet.NewWalletFromFile(outPath)
require.NoError(t, err)
expected, err := wallet.NewWalletFromFile("testdata/wallets/testwallet_NEO3.json")
require.NoError(t, err)
require.Equal(t, len(actual.Accounts), len(expected.Accounts))
for _, exp := range expected.Accounts {
addr, err := address.StringToUint160(exp.Address)
require.NoError(t, err)
act := actual.GetAccount(addr)
require.NotNil(t, act)
require.Equal(t, exp, act)
}
}

View file

@ -879,8 +879,12 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
for _, p := range n.Args[1:] {
params = append(params, c.scTypeFromExpr(p))
}
name := constant.StringVal(tv.Value)
c.emittedEvents[name] = append(c.emittedEvents[name], params)
// Sometimes event name is stored in a var.
// Skip in this case.
if tv.Value != nil {
name := constant.StringVal(tv.Value)
c.emittedEvents[name] = append(c.emittedEvents[name], params)
}
}
c.convertSyscall(n, f.pkg.Name(), f.name)
default:

View file

@ -195,8 +195,7 @@ func TestCreateBasicChain(t *testing.T) {
priv0 := testchain.PrivateKeyByID(0)
priv1 := testchain.PrivateKeyByID(1)
priv0ScriptHash := priv0.GetScriptHash()
acc0, err := wallet.NewAccountFromWIF(priv0.WIF())
require.NoError(t, err)
acc0 := wallet.NewAccountFromPrivateKey(priv0)
// Prepare some transaction for future submission.
txSendRaw := newNEP17Transfer(bc.contracts.NEO.Hash, priv0ScriptHash, priv1.GetScriptHash(), int64(util.Fixed8FromInt64(1000)))
@ -268,8 +267,7 @@ func initBasicChain(t *testing.T, bc *Blockchain) {
b.Header().EncodeBinary(buf.BinWriter)
t.Logf("header: %s", hex.EncodeToString(buf.Bytes()))
acc0, err := wallet.NewAccountFromWIF(priv0.WIF())
require.NoError(t, err)
acc0 := wallet.NewAccountFromPrivateKey(priv0)
// Push some contract into the chain.
txDeploy, cHash := newDeployTx(t, priv0ScriptHash, prefix+"test_contract.go", "Rubl")

View file

@ -132,16 +132,14 @@ func TestAddNetworkFee(t *testing.T) {
t.Run("Contract", func(t *testing.T) {
tx := transaction.New(testchain.Network(), []byte{byte(opcode.PUSH1)}, 0)
priv := testchain.PrivateKeyByID(0)
acc1, err := wallet.NewAccountFromWIF(priv.WIF())
require.NoError(t, err)
acc1 := wallet.NewAccountFromPrivateKey(priv)
acc1.Contract.Deployed = true
acc1.Contract.Script, _ = hex.DecodeString(verifyContractAVM)
h, _ := util.Uint160DecodeStringLE(verifyContractHash)
tx.ValidUntilBlock = chain.BlockHeight() + 10
t.Run("Valid", func(t *testing.T) {
acc0, err := wallet.NewAccountFromWIF(priv.WIF())
require.NoError(t, err)
acc0 := wallet.NewAccountFromPrivateKey(priv)
tx.Signers = []transaction.Signer{
{
Account: acc0.PrivateKey().GetScriptHash(),
@ -173,8 +171,7 @@ func TestAddNetworkFee(t *testing.T) {
require.Error(t, c.AddNetworkFee(tx, 10, acc0, acc1))
})
t.Run("InvalidContract", func(t *testing.T) {
acc0, err := wallet.NewAccountFromWIF(priv.WIF())
require.NoError(t, err)
acc0 := wallet.NewAccountFromPrivateKey(priv)
tx.Signers = []transaction.Signer{
{
Account: acc0.PrivateKey().GetScriptHash(),
@ -200,8 +197,7 @@ func TestSignAndPushInvocationTx(t *testing.T) {
require.NoError(t, c.Init())
priv := testchain.PrivateKey(0)
acc, err := wallet.NewAccountFromWIF(priv.WIF())
require.NoError(t, err)
acc := wallet.NewAccountFromPrivateKey(priv)
h, err := c.SignAndPushInvocationTx([]byte{byte(opcode.PUSH1)}, acc, 30, 0, []transaction.Signer{{
Account: priv.GetScriptHash(),
Scopes: transaction.CalledByEntry,
@ -239,8 +235,7 @@ func TestCreateTxFromScript(t *testing.T) {
require.NoError(t, c.Init())
priv := testchain.PrivateKey(0)
acc, err := wallet.NewAccountFromWIF(priv.WIF())
require.NoError(t, err)
acc := wallet.NewAccountFromPrivateKey(priv)
t.Run("NoSystemFee", func(t *testing.T) {
tx, err := c.CreateTxFromScript([]byte{byte(opcode.PUSH1)}, acc, -1, 10)
require.NoError(t, err)
@ -269,8 +264,7 @@ func TestCreateNEP17TransferTx(t *testing.T) {
require.NoError(t, c.Init())
priv := testchain.PrivateKeyByID(0)
acc, err := wallet.NewAccountFromWIF(priv.WIF())
require.NoError(t, err)
acc := wallet.NewAccountFromPrivateKey(priv)
gasContractHash, err := c.GetNativeContractHash("gas")
require.NoError(t, err)

View file

@ -996,8 +996,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) []
})
priv0 := testchain.PrivateKeyByID(0)
acc0, err := wallet.NewAccountFromWIF(priv0.WIF())
require.NoError(t, err)
acc0 := wallet.NewAccountFromPrivateKey(priv0)
addNetworkFee := func(tx *transaction.Transaction) {
size := io.GetVarSize(tx)

View file

@ -90,7 +90,7 @@ func NewAccount() (*Account, error) {
if err != nil {
return nil, err
}
return newAccountFromPrivateKey(priv), nil
return NewAccountFromPrivateKey(priv), nil
}
// SignTx signs transaction t and updates it's Witnesses.
@ -172,7 +172,7 @@ func NewAccountFromWIF(wif string) (*Account, error) {
if err != nil {
return nil, err
}
return newAccountFromPrivateKey(privKey), nil
return NewAccountFromPrivateKey(privKey), nil
}
// NewAccountFromEncryptedWIF creates a new Account from the given encrypted WIF.
@ -182,7 +182,7 @@ func NewAccountFromEncryptedWIF(wif string, pass string) (*Account, error) {
return nil, err
}
a := newAccountFromPrivateKey(priv)
a := NewAccountFromPrivateKey(priv)
a.EncryptedWIF = wif
return a, nil
@ -216,8 +216,8 @@ func (a *Account) ConvertMultisig(m int, pubs []*keys.PublicKey) error {
return nil
}
// newAccountFromPrivateKey creates a wallet from the given PrivateKey.
func newAccountFromPrivateKey(p *keys.PrivateKey) *Account {
// NewAccountFromPrivateKey creates a wallet from the given PrivateKey.
func NewAccountFromPrivateKey(p *keys.PrivateKey) *Account {
pubKey := p.PublicKey()
pubAddr := p.Address()
wif := p.WIF()