github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/smartcontract/manifest/parameter.go (about) 1 package manifest 2 3 import ( 4 "errors" 5 "fmt" 6 "sort" 7 8 "github.com/nspcc-dev/neo-go/pkg/smartcontract" 9 "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" 10 ) 11 12 // Parameter represents smartcontract's parameter's definition. 13 type Parameter struct { 14 Name string `json:"name"` 15 Type smartcontract.ParamType `json:"type"` 16 } 17 18 // Parameters is just an array of Parameter. 19 type Parameters []Parameter 20 21 // NewParameter returns a new parameter of the specified name and type. 22 func NewParameter(name string, typ smartcontract.ParamType) Parameter { 23 return Parameter{ 24 Name: name, 25 Type: typ, 26 } 27 } 28 29 // IsValid checks Parameter consistency and correctness. 30 func (p *Parameter) IsValid() error { 31 if p.Name == "" { 32 return errors.New("empty or absent name") 33 } 34 if p.Type == smartcontract.VoidType { 35 return errors.New("void parameter") 36 } 37 _, err := smartcontract.ConvertToParamType(int(p.Type)) 38 return err 39 } 40 41 // ToStackItem converts Parameter to stackitem.Item. 42 func (p *Parameter) ToStackItem() stackitem.Item { 43 return stackitem.NewStruct([]stackitem.Item{ 44 stackitem.Make(p.Name), 45 stackitem.Make(int(p.Type)), 46 }) 47 } 48 49 // FromStackItem converts stackitem.Item to Parameter. 50 func (p *Parameter) FromStackItem(item stackitem.Item) error { 51 var err error 52 if item.Type() != stackitem.StructT { 53 return errors.New("invalid Parameter stackitem type") 54 } 55 param := item.Value().([]stackitem.Item) 56 if len(param) != 2 { 57 return errors.New("invalid Parameter stackitem length") 58 } 59 p.Name, err = stackitem.ToString(param[0]) 60 if err != nil { 61 return err 62 } 63 typ, err := param[1].TryInteger() 64 if err != nil { 65 return err 66 } 67 p.Type, err = smartcontract.ConvertToParamType(int(typ.Int64())) 68 if err != nil { 69 return err 70 } 71 return nil 72 } 73 74 // AreValid checks all parameters for validity and consistency. 75 func (p Parameters) AreValid() error { 76 for i := range p { 77 err := p[i].IsValid() 78 if err != nil { 79 return fmt.Errorf("parameter #%d/%q: %w", i, p[i].Name, err) 80 } 81 } 82 if len(p) < 2 { 83 return nil 84 } 85 names := make([]string, len(p)) 86 for i := range p { 87 names[i] = p[i].Name 88 } 89 if stringsHaveDups(names) { 90 return errors.New("duplicate parameter name") 91 } 92 return nil 93 } 94 95 // stringsHaveDups checks the given set of strings for duplicates. It modifies the slice given! 96 func stringsHaveDups(strings []string) bool { 97 sort.Strings(strings) 98 for i := range strings { 99 if i == 0 { 100 continue 101 } 102 if strings[i] == strings[i-1] { 103 return true 104 } 105 } 106 return false 107 } 108 109 // permissionDescsHaveDups checks the given set of strings for duplicates. It modifies the slice given! 110 func permissionDescsHaveDups(descs []PermissionDesc) bool { 111 sort.Slice(descs, func(i, j int) bool { 112 return descs[i].Less(descs[j]) 113 }) 114 for i := range descs { 115 if i == 0 { 116 continue 117 } 118 j := i - 1 119 if descs[i].Type != descs[j].Type { 120 continue 121 } 122 switch descs[i].Type { 123 case PermissionWildcard: 124 return true 125 case PermissionHash: 126 if descs[i].Hash() == descs[j].Hash() { 127 return true 128 } 129 case PermissionGroup: 130 if descs[i].Group().Cmp(descs[j].Group()) == 0 { 131 return true 132 } 133 } 134 } 135 return false 136 }