cli: add util ops command

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
This commit is contained in:
Anna Shaleva 2023-04-11 18:45:50 +03:00
parent fdec8ea3f7
commit 541da7e83b
2 changed files with 91 additions and 0 deletions

View file

@ -1,10 +1,14 @@
package util
import (
"encoding/base64"
"encoding/hex"
"fmt"
"os"
"github.com/nspcc-dev/neo-go/cli/options"
vmcli "github.com/nspcc-dev/neo-go/cli/vm"
"github.com/nspcc-dev/neo-go/pkg/vm"
"github.com/urfave/cli"
)
@ -44,6 +48,22 @@ func NewCommands() []cli.Command {
Action: txDump,
Flags: txDumpFlags,
},
{
Name: "ops",
Usage: "Pretty-print VM opcodes of the given base64- or hex- encoded script (base64 is checked first). If the input file is specified, then the script is taken from the file.",
UsageText: "ops <base64/hex-encoded script> [-i path-to-file] [--hex]",
Action: handleOps,
Flags: []cli.Flag{
cli.StringFlag{
Name: "in, i",
Usage: "input file containing base64- or hex- encoded script representation",
},
cli.BoolFlag{
Name: "hex",
Usage: "use hex encoding and do not check base64",
},
},
},
},
},
}
@ -57,3 +77,35 @@ func handleParse(ctx *cli.Context) error {
fmt.Fprint(ctx.App.Writer, res)
return nil
}
func handleOps(ctx *cli.Context) error {
var (
s string
err error
b []byte
)
in := ctx.String("in")
if len(in) != 0 {
b, err := os.ReadFile(in)
if err != nil {
return cli.NewExitError(fmt.Errorf("failed to read file: %w", err), 1)
}
s = string(b)
} else {
if !ctx.Args().Present() {
return cli.NewExitError("missing script", 1)
}
s = ctx.Args()[0]
}
b, err = base64.StdEncoding.DecodeString(s)
if err != nil || ctx.Bool("hex") {
b, err = hex.DecodeString(s)
}
if err != nil {
return cli.NewExitError("unknown encoding: base64 or hex are supported", 1)
}
v := vm.New()
v.LoadScript(b)
v.PrintOps(ctx.App.Writer)
return nil
}

View file

@ -1,10 +1,13 @@
package util_test
import (
"os"
"path/filepath"
"testing"
"github.com/nspcc-dev/neo-go/internal/testcli"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/stretchr/testify/require"
)
func TestUtilConvert(t *testing.T) {
@ -24,3 +27,39 @@ func TestUtilConvert(t *testing.T) {
e.CheckNextLine(t, "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzMDIwMQ==") // string to base64
e.CheckEOF(t)
}
func TestUtilOps(t *testing.T) {
e := testcli.NewExecutor(t, false)
base64Str := "EUA="
hexStr := "1140"
check := func(t *testing.T) {
e.CheckNextLine(t, "INDEX.*OPCODE.*PARAMETER")
e.CheckNextLine(t, "PUSH1")
e.CheckNextLine(t, "RET")
e.CheckEOF(t)
}
e.Run(t, "neo-go", "util", "ops", base64Str) // base64
check(t)
e.Run(t, "neo-go", "util", "ops", hexStr) // base64 is checked firstly by default, but it's invalid script if decoded from base64
e.CheckNextLine(t, "INDEX.*OPCODE.*PARAMETER")
e.CheckNextLine(t, ".*ERROR: incorrect opcode")
e.CheckEOF(t)
e.Run(t, "neo-go", "util", "ops", "--hex", hexStr) // explicitly specify hex encoding
check(t)
e.RunWithError(t, "neo-go", "util", "ops", "%&~*") // unknown encoding
tmp := filepath.Join(t.TempDir(), "script_base64.txt")
require.NoError(t, os.WriteFile(tmp, []byte(base64Str), os.ModePerm))
e.Run(t, "neo-go", "util", "ops", "--in", tmp) // base64 from file
check(t)
tmp = filepath.Join(t.TempDir(), "script_hex.txt")
require.NoError(t, os.WriteFile(tmp, []byte(hexStr), os.ModePerm))
e.Run(t, "neo-go", "util", "ops", "--hex", "--in", tmp) // hex from file
check(t)
}