manifest: add ABI validity check

Some methods must be defined in a valid ABI. Refs. neo-project/neo#2263.
This commit is contained in:
Roman Khimov 2021-02-08 13:15:10 +03:00
parent 5ba074b4cf
commit 1a4958b1d5
4 changed files with 31 additions and 1 deletions

View file

@ -8,6 +8,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/interop" "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/state"
"github.com/nspcc-dev/neo-go/pkg/core/storage" "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/manifest"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" "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"
@ -23,6 +24,11 @@ func TestDeployGetUpdateDestroyContract(t *testing.T) {
ne, err := nef.NewFile(script) ne, err := nef.NewFile(script)
require.NoError(t, err) require.NoError(t, err)
manif := manifest.NewManifest("Test") 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) h := state.CreateContractHash(sender, ne.Checksum, manif.Name)

View file

@ -49,6 +49,14 @@ func (a *ABI) GetEvent(name string) *Event {
return nil 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. // ToStackItem converts ABI to stackitem.Item.
func (a *ABI) ToStackItem() stackitem.Item { func (a *ABI) ToStackItem() stackitem.Item {
methods := make([]stackitem.Item, len(a.Methods)) methods := make([]stackitem.Item, len(a.Methods))

View file

@ -70,9 +70,15 @@ func (m *Manifest) CanCall(hash util.Uint160, toCall *Manifest, method string) b
return false 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 { func (m *Manifest) IsValid(hash util.Uint160) error {
var err error var err error
err = m.ABI.IsValid()
if err != nil {
return err
}
for _, g := range m.Groups { for _, g := range m.Groups {
err = g.IsValid(hash) err = g.IsValid(hash)
if err != nil { if err != nil {

View file

@ -111,6 +111,16 @@ func TestIsValid(t *testing.T) {
contractHash := util.Uint160{1, 2, 3} contractHash := util.Uint160{1, 2, 3}
m := NewManifest("Test") 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) { t.Run("valid, no groups", func(t *testing.T) {
require.NoError(t, m.IsValid(contractHash)) require.NoError(t, m.IsValid(contractHash))
}) })