manifest: add duplicate events/methods checks to ABI

Refs. #1699.
This commit is contained in:
Roman Khimov 2021-02-08 23:53:22 +03:00
parent 62ef5a8dc7
commit a3abdbd7f0
2 changed files with 79 additions and 0 deletions

View file

@ -2,6 +2,7 @@ package manifest
import ( import (
"errors" "errors"
"sort"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
) )
@ -60,12 +61,49 @@ func (a *ABI) IsValid() error {
return err return err
} }
} }
if len(a.Methods) > 1 {
methods := make([]struct {
name string
params int
}, len(a.Methods))
for i := range methods {
methods[i].name = a.Methods[i].Name
methods[i].params = len(a.Methods[i].Parameters)
}
sort.Slice(methods, func(i, j int) bool {
if methods[i].name < methods[j].name {
return true
}
if methods[i].name == methods[j].name {
return methods[i].params < methods[j].params
}
return false
})
for i := range methods {
if i == 0 {
continue
}
if methods[i].name == methods[i-1].name &&
methods[i].params == methods[i-1].params {
return errors.New("duplicate method specifications")
}
}
}
for i := range a.Events { for i := range a.Events {
err := a.Events[i].IsValid() err := a.Events[i].IsValid()
if err != nil { if err != nil {
return err return err
} }
} }
if len(a.Events) > 1 {
names := make([]string, len(a.Events))
for i := range a.Events {
names[i] = a.Events[i].Name
}
if stringsHaveDups(names) {
return errors.New("duplicate event names")
}
}
return nil return nil
} }

View file

@ -0,0 +1,41 @@
package manifest
import (
"testing"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/stretchr/testify/require"
)
func TestABIIsValid(t *testing.T) {
a := &ABI{}
require.Error(t, a.IsValid()) // No methods.
a.Methods = append(a.Methods, Method{Name: "qwe"})
require.NoError(t, a.IsValid())
a.Methods = append(a.Methods, Method{Name: "qaz"})
require.NoError(t, a.IsValid())
a.Methods = append(a.Methods, Method{Name: "qaz", Offset: -42})
require.Error(t, a.IsValid())
a.Methods = append(a.Methods[:len(a.Methods)-1], Method{Name: "qwe", Parameters: []Parameter{NewParameter("param", smartcontract.BoolType)}})
require.NoError(t, a.IsValid())
a.Methods = append(a.Methods, Method{Name: "qwe"})
require.Error(t, a.IsValid())
a.Methods = a.Methods[:len(a.Methods)-1]
a.Events = append(a.Events, Event{Name: "wsx"})
require.NoError(t, a.IsValid())
a.Events = append(a.Events, Event{})
require.Error(t, a.IsValid())
a.Events = append(a.Events[:len(a.Events)-1], Event{Name: "edc"})
require.NoError(t, a.IsValid())
a.Events = append(a.Events, Event{Name: "wsx"})
require.Error(t, a.IsValid())
}