From 1a4958b1d570700a88710ff391ee131af81206ee Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Mon, 8 Feb 2021 13:15:10 +0300 Subject: [PATCH] manifest: add ABI validity check Some methods must be defined in a valid ABI. Refs. neo-project/neo#2263. --- pkg/core/native/management_test.go | 6 ++++++ pkg/smartcontract/manifest/abi.go | 8 ++++++++ pkg/smartcontract/manifest/manifest.go | 8 +++++++- pkg/smartcontract/manifest/manifest_test.go | 10 ++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/pkg/core/native/management_test.go b/pkg/core/native/management_test.go index 61fbd8b95..ffa6a0c88 100644 --- a/pkg/core/native/management_test.go +++ b/pkg/core/native/management_test.go @@ -8,6 +8,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/interop" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/storage" + "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" "github.com/nspcc-dev/neo-go/pkg/util" @@ -23,6 +24,11 @@ func TestDeployGetUpdateDestroyContract(t *testing.T) { ne, err := nef.NewFile(script) require.NoError(t, err) manif := manifest.NewManifest("Test") + manif.ABI.Methods = append(manif.ABI.Methods, manifest.Method{ + Name: "dummy", + ReturnType: smartcontract.VoidType, + Parameters: []manifest.Parameter{}, + }) h := state.CreateContractHash(sender, ne.Checksum, manif.Name) diff --git a/pkg/smartcontract/manifest/abi.go b/pkg/smartcontract/manifest/abi.go index 7a83893d5..ee14e25c9 100644 --- a/pkg/smartcontract/manifest/abi.go +++ b/pkg/smartcontract/manifest/abi.go @@ -49,6 +49,14 @@ func (a *ABI) GetEvent(name string) *Event { return nil } +// IsValid checks ABI consistency and correctness. +func (a *ABI) IsValid() error { + if len(a.Methods) == 0 { + return errors.New("ABI contains no methods") + } + return nil +} + // ToStackItem converts ABI to stackitem.Item. func (a *ABI) ToStackItem() stackitem.Item { methods := make([]stackitem.Item, len(a.Methods)) diff --git a/pkg/smartcontract/manifest/manifest.go b/pkg/smartcontract/manifest/manifest.go index d8afdd5a9..45f300e67 100644 --- a/pkg/smartcontract/manifest/manifest.go +++ b/pkg/smartcontract/manifest/manifest.go @@ -70,9 +70,15 @@ func (m *Manifest) CanCall(hash util.Uint160, toCall *Manifest, method string) b return false } -// IsValid checks whether the hash given is correct wrt manifest's groups. +// IsValid checks manifest internal consistency and correctness, one of the +// checks is for group signature correctness, contract hash is passed for it. func (m *Manifest) IsValid(hash util.Uint160) error { var err error + + err = m.ABI.IsValid() + if err != nil { + return err + } for _, g := range m.Groups { err = g.IsValid(hash) if err != nil { diff --git a/pkg/smartcontract/manifest/manifest_test.go b/pkg/smartcontract/manifest/manifest_test.go index c92dcd289..fdf594d32 100644 --- a/pkg/smartcontract/manifest/manifest_test.go +++ b/pkg/smartcontract/manifest/manifest_test.go @@ -111,6 +111,16 @@ func TestIsValid(t *testing.T) { contractHash := util.Uint160{1, 2, 3} m := NewManifest("Test") + t.Run("invalid, no ABI methods", func(t *testing.T) { + require.Error(t, m.IsValid(contractHash)) + }) + + m.ABI.Methods = append(m.ABI.Methods, Method{ + Name: "dummy", + ReturnType: smartcontract.VoidType, + Parameters: []Parameter{}, + }) + t.Run("valid, no groups", func(t *testing.T) { require.NoError(t, m.IsValid(contractHash)) })