mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-23 13:41:37 +00:00
parent
15ed905757
commit
284476c070
5 changed files with 165 additions and 10 deletions
|
@ -82,10 +82,10 @@ func (m *Manifest) IsValid(hash util.Uint160) error {
|
||||||
for _, g := range m.Groups {
|
for _, g := range m.Groups {
|
||||||
err = g.IsValid(hash)
|
err = g.IsValid(hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Permissions(m.Permissions).AreValid()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToStackItem converts Manifest to stackitem.Item.
|
// ToStackItem converts Manifest to stackitem.Item.
|
||||||
|
|
|
@ -147,6 +147,17 @@ func TestIsValid(t *testing.T) {
|
||||||
})
|
})
|
||||||
m.ABI.Events = m.ABI.Events[:1]
|
m.ABI.Events = m.ABI.Events[:1]
|
||||||
|
|
||||||
|
m.Permissions = append(m.Permissions, *NewPermission(PermissionHash, util.Uint160{1, 2, 3}))
|
||||||
|
t.Run("valid, with permissions", func(t *testing.T) {
|
||||||
|
require.NoError(t, m.IsValid(contractHash))
|
||||||
|
})
|
||||||
|
|
||||||
|
m.Permissions = append(m.Permissions, *NewPermission(PermissionHash, util.Uint160{1, 2, 3}))
|
||||||
|
t.Run("invalid, with permissions", func(t *testing.T) {
|
||||||
|
require.Error(t, m.IsValid(contractHash))
|
||||||
|
})
|
||||||
|
m.Permissions = m.Permissions[:1]
|
||||||
|
|
||||||
t.Run("with groups", func(t *testing.T) {
|
t.Run("with groups", func(t *testing.T) {
|
||||||
m.Groups = make([]Group, 3)
|
m.Groups = make([]Group, 3)
|
||||||
pks := make([]*keys.PrivateKey, 3)
|
pks := make([]*keys.PrivateKey, 3)
|
||||||
|
|
|
@ -85,14 +85,22 @@ func (p Parameters) AreValid() error {
|
||||||
for i := range p {
|
for i := range p {
|
||||||
names[i] = p[i].Name
|
names[i] = p[i].Name
|
||||||
}
|
}
|
||||||
sort.Strings(names)
|
if stringsHaveDups(names) {
|
||||||
for i := range names {
|
|
||||||
if i == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if names[i] == names[i-1] {
|
|
||||||
return errors.New("duplicate parameter name")
|
return errors.New("duplicate parameter name")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// stringsHaveDups checks given set of strings for duplicates. It modifies the slice given!
|
||||||
|
func stringsHaveDups(strings []string) bool {
|
||||||
|
sort.Strings(strings)
|
||||||
|
for i := range strings {
|
||||||
|
if i == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings[i] == strings[i-1] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
@ -36,6 +37,9 @@ type Permission struct {
|
||||||
Methods WildStrings `json:"methods"`
|
Methods WildStrings `json:"methods"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Permissions is just an array of Permission.
|
||||||
|
type Permissions []Permission
|
||||||
|
|
||||||
type permissionAux struct {
|
type permissionAux struct {
|
||||||
Contract PermissionDesc `json:"contract"`
|
Contract PermissionDesc `json:"contract"`
|
||||||
Methods WildStrings `json:"methods"`
|
Methods WildStrings `json:"methods"`
|
||||||
|
@ -85,6 +89,82 @@ func (d *PermissionDesc) Group() *keys.PublicKey {
|
||||||
return d.Value.(*keys.PublicKey)
|
return d.Value.(*keys.PublicKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsValid checks if Permission is correct.
|
||||||
|
func (p *Permission) IsValid() error {
|
||||||
|
for i := range p.Methods.Value {
|
||||||
|
if p.Methods.Value[i] == "" {
|
||||||
|
return errors.New("empty method name")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(p.Methods.Value) < 2 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
names := make([]string, len(p.Methods.Value))
|
||||||
|
copy(names, p.Methods.Value)
|
||||||
|
if stringsHaveDups(names) {
|
||||||
|
return errors.New("duplicate method names")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AreValid checks each Permission and ensures there are no duplicates.
|
||||||
|
func (ps Permissions) AreValid() error {
|
||||||
|
for i := range ps {
|
||||||
|
err := ps[i].IsValid()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(ps) < 2 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
contracts := make([]PermissionDesc, 0, len(ps))
|
||||||
|
for i := range ps {
|
||||||
|
contracts = append(contracts, ps[i].Contract)
|
||||||
|
}
|
||||||
|
sort.Slice(contracts, func(i, j int) bool {
|
||||||
|
if contracts[i].Type < contracts[j].Type {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if contracts[i].Type != contracts[j].Type {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
switch contracts[i].Type {
|
||||||
|
case PermissionHash:
|
||||||
|
return contracts[i].Hash().Less(contracts[j].Hash())
|
||||||
|
case PermissionGroup:
|
||||||
|
return contracts[i].Group().Cmp(contracts[j].Group()) < 0
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
for i := range contracts {
|
||||||
|
if i == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
j := i - 1
|
||||||
|
if contracts[i].Type != contracts[j].Type {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var bad bool
|
||||||
|
switch contracts[i].Type {
|
||||||
|
case PermissionWildcard:
|
||||||
|
bad = true
|
||||||
|
case PermissionHash:
|
||||||
|
if contracts[i].Hash() == contracts[j].Hash() {
|
||||||
|
bad = true
|
||||||
|
}
|
||||||
|
case PermissionGroup:
|
||||||
|
if contracts[i].Group().Cmp(contracts[j].Group()) == 0 {
|
||||||
|
bad = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if bad {
|
||||||
|
return errors.New("duplicate contracts")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// IsAllowed checks if method is allowed to be executed.
|
// IsAllowed checks if method is allowed to be executed.
|
||||||
func (p *Permission) IsAllowed(hash util.Uint160, m *Manifest, method string) bool {
|
func (p *Permission) IsAllowed(hash util.Uint160, m *Manifest, method string) bool {
|
||||||
switch p.Contract.Type {
|
switch p.Contract.Type {
|
||||||
|
|
|
@ -21,6 +21,62 @@ func TestNewPermission(t *testing.T) {
|
||||||
require.Panics(t, func() { NewPermission(PermissionGroup, util.Uint160{}) })
|
require.Panics(t, func() { NewPermission(PermissionGroup, util.Uint160{}) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPermissionIsValid(t *testing.T) {
|
||||||
|
p := Permission{}
|
||||||
|
require.NoError(t, p.IsValid())
|
||||||
|
|
||||||
|
p.Methods.Add("")
|
||||||
|
require.Error(t, p.IsValid())
|
||||||
|
|
||||||
|
p.Methods.Value = nil
|
||||||
|
p.Methods.Add("qwerty")
|
||||||
|
require.NoError(t, p.IsValid())
|
||||||
|
|
||||||
|
p.Methods.Add("poiuyt")
|
||||||
|
require.NoError(t, p.IsValid())
|
||||||
|
|
||||||
|
p.Methods.Add("qwerty")
|
||||||
|
require.Error(t, p.IsValid())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPermissionsAreValid(t *testing.T) {
|
||||||
|
p := Permissions{}
|
||||||
|
require.NoError(t, p.AreValid())
|
||||||
|
|
||||||
|
p = append(p, Permission{Methods: WildStrings{Value: []string{""}}})
|
||||||
|
require.Error(t, p.AreValid())
|
||||||
|
|
||||||
|
p = p[:0]
|
||||||
|
p = append(p, *NewPermission(PermissionHash, util.Uint160{1, 2, 3}))
|
||||||
|
require.NoError(t, p.AreValid())
|
||||||
|
|
||||||
|
priv0, err := keys.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
priv1, err := keys.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
p = append(p, *NewPermission(PermissionGroup, priv0.PublicKey()))
|
||||||
|
require.NoError(t, p.AreValid())
|
||||||
|
|
||||||
|
p = append(p, *NewPermission(PermissionGroup, priv1.PublicKey()))
|
||||||
|
require.NoError(t, p.AreValid())
|
||||||
|
|
||||||
|
p = append(p, *NewPermission(PermissionWildcard))
|
||||||
|
require.NoError(t, p.AreValid())
|
||||||
|
|
||||||
|
p = append(p, *NewPermission(PermissionHash, util.Uint160{3, 2, 1}))
|
||||||
|
require.NoError(t, p.AreValid())
|
||||||
|
|
||||||
|
p = append(p, *NewPermission(PermissionWildcard))
|
||||||
|
require.Error(t, p.AreValid())
|
||||||
|
|
||||||
|
p = append(p[:len(p)-1], *NewPermission(PermissionHash, util.Uint160{1, 2, 3}))
|
||||||
|
require.Error(t, p.AreValid())
|
||||||
|
|
||||||
|
p = append(p[:len(p)-1], *NewPermission(PermissionGroup, priv0.PublicKey()))
|
||||||
|
require.Error(t, p.AreValid())
|
||||||
|
}
|
||||||
|
|
||||||
func TestPermission_MarshalJSON(t *testing.T) {
|
func TestPermission_MarshalJSON(t *testing.T) {
|
||||||
t.Run("wildcard", func(t *testing.T) {
|
t.Run("wildcard", func(t *testing.T) {
|
||||||
expected := NewPermission(PermissionWildcard)
|
expected := NewPermission(PermissionWildcard)
|
||||||
|
|
Loading…
Reference in a new issue