forked from TrueCloudLab/neoneo-go
cli: allow to calculate contract hash before deployment
This commit is contained in:
parent
f2365e2392
commit
c49eb86a2e
2 changed files with 99 additions and 0 deletions
|
@ -9,14 +9,63 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/internal/random"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
|
"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"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
|
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestCalcHash(t *testing.T) {
|
||||||
|
e := newExecutor(t, false)
|
||||||
|
defer e.Close(t)
|
||||||
|
|
||||||
|
nefPath := "./testdata/verify.nef"
|
||||||
|
src, err := ioutil.ReadFile(nefPath)
|
||||||
|
require.NoError(t, err)
|
||||||
|
nefF, err := nef.FileFromBytes(src)
|
||||||
|
require.NoError(t, err)
|
||||||
|
sender := random.Uint160()
|
||||||
|
|
||||||
|
cmd := []string{"neo-go", "contract", "calc-hash"}
|
||||||
|
t.Run("no sender", func(t *testing.T) {
|
||||||
|
e.RunWithError(t, append(cmd, "--in", nefPath)...)
|
||||||
|
})
|
||||||
|
t.Run("no nef file", func(t *testing.T) {
|
||||||
|
e.RunWithError(t, append(cmd, "--sender", sender.StringLE())...)
|
||||||
|
})
|
||||||
|
t.Run("invalid path", func(t *testing.T) {
|
||||||
|
e.RunWithError(t, append(cmd, "--sender", sender.StringLE(),
|
||||||
|
"--in", "./testdata/verify.nef123")...)
|
||||||
|
})
|
||||||
|
t.Run("invalid file", func(t *testing.T) {
|
||||||
|
p := path.Join(os.TempDir(), "neogo.calchash.verify.nef")
|
||||||
|
defer os.Remove(p)
|
||||||
|
require.NoError(t, ioutil.WriteFile(p, src[:4], os.ModePerm))
|
||||||
|
e.RunWithError(t, append(cmd, "--sender", sender.StringLE(), "--in", p)...)
|
||||||
|
})
|
||||||
|
|
||||||
|
cmd = append(cmd, "--in", nefPath)
|
||||||
|
expected := state.CreateContractHash(sender, nefF.Script)
|
||||||
|
t.Run("valid, uint160", func(t *testing.T) {
|
||||||
|
e.Run(t, append(cmd, "--sender", sender.StringLE())...)
|
||||||
|
e.checkNextLine(t, expected.StringLE())
|
||||||
|
})
|
||||||
|
t.Run("valid, uint160 with 0x", func(t *testing.T) {
|
||||||
|
e.Run(t, append(cmd, "--sender", "0x"+sender.StringLE())...)
|
||||||
|
e.checkNextLine(t, expected.StringLE())
|
||||||
|
})
|
||||||
|
t.Run("valid, address", func(t *testing.T) {
|
||||||
|
e.Run(t, append(cmd, "--sender", address.Uint160ToString(sender))...)
|
||||||
|
e.checkNextLine(t, expected.StringLE())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestContractInitAndCompile(t *testing.T) {
|
func TestContractInitAndCompile(t *testing.T) {
|
||||||
tmpDir := path.Join(os.TempDir(), "neogo.inittest")
|
tmpDir := path.Join(os.TempDir(), "neogo.inittest")
|
||||||
require.NoError(t, os.Mkdir(tmpDir, os.ModePerm))
|
require.NoError(t, os.Mkdir(tmpDir, os.ModePerm))
|
||||||
|
@ -139,6 +188,12 @@ func TestComlileAndInvokeFunction(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
e.checkTxPersisted(t)
|
e.checkTxPersisted(t)
|
||||||
|
|
||||||
|
t.Run("check calc hash", func(t *testing.T) {
|
||||||
|
e.Run(t, "neo-go", "contract", "calc-hash",
|
||||||
|
"--sender", validatorAddr, "--in", nefName)
|
||||||
|
e.checkNextLine(t, h.StringLE())
|
||||||
|
})
|
||||||
|
|
||||||
cmd := []string{"neo-go", "contract", "testinvokefunction",
|
cmd := []string{"neo-go", "contract", "testinvokefunction",
|
||||||
"--rpc-endpoint", "http://" + e.RPC.Addr}
|
"--rpc-endpoint", "http://" + e.RPC.Addr}
|
||||||
t.Run("missing hash", func(t *testing.T) {
|
t.Run("missing hash", func(t *testing.T) {
|
||||||
|
|
|
@ -337,6 +337,21 @@ func NewCommands() []cli.Command {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "calc-hash",
|
||||||
|
Usage: "calculates hash of a contract after deployment",
|
||||||
|
Action: calcHash,
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "sender, s",
|
||||||
|
Usage: "sender script hash or address",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "in",
|
||||||
|
Usage: "path to NEF file",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
@ -440,6 +455,35 @@ func contractCompile(ctx *cli.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func calcHash(ctx *cli.Context) error {
|
||||||
|
s := ctx.String("sender")
|
||||||
|
u, err := address.StringToUint160(s)
|
||||||
|
if err != nil {
|
||||||
|
if strings.HasPrefix(s, "0x") {
|
||||||
|
s = s[2:]
|
||||||
|
}
|
||||||
|
u, err = util.Uint160DecodeStringLE(s)
|
||||||
|
if err != nil {
|
||||||
|
return cli.NewExitError(errors.New("invalid sender: must be either address or Uint160 in LE form"), 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p := ctx.String("in")
|
||||||
|
if p == "" {
|
||||||
|
return cli.NewExitError(errors.New("no .nef file was provided"), 1)
|
||||||
|
}
|
||||||
|
f, err := ioutil.ReadFile(p)
|
||||||
|
if err != nil {
|
||||||
|
return cli.NewExitError(fmt.Errorf("can't read .nef file: %w", err), 1)
|
||||||
|
}
|
||||||
|
nefFile, err := nef.FileFromBytes(f)
|
||||||
|
if err != nil {
|
||||||
|
return cli.NewExitError(fmt.Errorf("can't unmarshal .nef file: %w", err), 1)
|
||||||
|
}
|
||||||
|
fmt.Fprintln(ctx.App.Writer, "Contract hash:", state.CreateContractHash(u, nefFile.Script).StringLE())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func testInvokeFunction(ctx *cli.Context) error {
|
func testInvokeFunction(ctx *cli.Context) error {
|
||||||
return invokeInternal(ctx, false)
|
return invokeInternal(ctx, false)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue