github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/cli/smartcontract/permission.go (about) 1 package smartcontract 2 3 import ( 4 "errors" 5 "fmt" 6 7 "github.com/nspcc-dev/neo-go/pkg/crypto/keys" 8 "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" 9 "github.com/nspcc-dev/neo-go/pkg/util" 10 "gopkg.in/yaml.v3" 11 ) 12 13 type permission manifest.Permission 14 15 const ( 16 permHashKey = "hash" 17 permGroupKey = "group" 18 permMethodKey = "methods" 19 ) 20 21 func (p permission) MarshalYAML() (any, error) { 22 m := yaml.Node{Kind: yaml.MappingNode} 23 switch p.Contract.Type { 24 case manifest.PermissionWildcard: 25 case manifest.PermissionHash: 26 m.Content = append(m.Content, 27 &yaml.Node{Kind: yaml.ScalarNode, Value: permHashKey}, 28 &yaml.Node{Kind: yaml.ScalarNode, Value: p.Contract.Value.(util.Uint160).StringLE()}) 29 case manifest.PermissionGroup: 30 m.Content = append(m.Content, 31 &yaml.Node{Kind: yaml.ScalarNode, Value: permGroupKey}, 32 &yaml.Node{Kind: yaml.ScalarNode, Value: p.Contract.Value.(*keys.PublicKey).StringCompressed()}) 33 default: 34 return nil, fmt.Errorf("invalid permission type: %d", p.Contract.Type) 35 } 36 37 var val any = "*" 38 if !p.Methods.IsWildcard() { 39 val = p.Methods.Value 40 } 41 42 n := &yaml.Node{Kind: yaml.ScalarNode} 43 err := n.Encode(val) 44 if err != nil { 45 return nil, err 46 } 47 m.Content = append(m.Content, 48 &yaml.Node{Kind: yaml.ScalarNode, Value: permMethodKey}, 49 n) 50 51 return m, nil 52 } 53 54 func (p *permission) UnmarshalYAML(unmarshal func(any) error) error { 55 var m map[string]any 56 if err := unmarshal(&m); err != nil { 57 return err 58 } 59 60 if err := p.fillType(m); err != nil { 61 return err 62 } 63 64 return p.fillMethods(m) 65 } 66 67 func (p *permission) fillType(m map[string]any) error { 68 vh, ok1 := m[permHashKey] 69 vg, ok2 := m[permGroupKey] 70 switch { 71 case ok1 && ok2: 72 return errors.New("permission must have either 'hash' or 'group' field") 73 case ok1: 74 s, ok := vh.(string) 75 if !ok { 76 return errors.New("invalid 'hash' type") 77 } 78 79 u, err := util.Uint160DecodeStringLE(s) 80 if err != nil { 81 return err 82 } 83 84 p.Contract.Type = manifest.PermissionHash 85 p.Contract.Value = u 86 case ok2: 87 s, ok := vg.(string) 88 if !ok { 89 return errors.New("invalid 'hash' type") 90 } 91 92 pub, err := keys.NewPublicKeyFromString(s) 93 if err != nil { 94 return err 95 } 96 97 p.Contract.Type = manifest.PermissionGroup 98 p.Contract.Value = pub 99 default: 100 p.Contract.Type = manifest.PermissionWildcard 101 } 102 return nil 103 } 104 105 func (p *permission) fillMethods(m map[string]any) error { 106 methods, ok := m[permMethodKey] 107 if !ok { 108 return errors.New("'methods' field is missing from permission") 109 } 110 111 switch mt := methods.(type) { 112 case string: 113 if mt == "*" { 114 p.Methods.Value = nil 115 return nil 116 } 117 case []any: 118 ms := make([]string, len(mt)) 119 for i := range mt { 120 ms[i], ok = mt[i].(string) 121 if !ok { 122 return errors.New("invalid permission method name") 123 } 124 } 125 p.Methods.Value = ms 126 return nil 127 default: 128 } 129 return errors.New("'methods' field is invalid") 130 }