github.com/aergoio/aergo@v1.3.1/contract/enterprise/config.go (about) 1 package enterprise 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/aergoio/aergo/state" 8 "github.com/aergoio/aergo/types" 9 ) 10 11 var confPrefix = []byte("conf\\") 12 13 const ( 14 RPCPermissions = "RPCPERMISSIONS" 15 P2PWhite = "P2PWHITE" 16 P2PBlack = "P2PBLACK" 17 AccountWhite = "ACCOUNTWHITE" 18 ) 19 20 //EnterpriseKeyDict is represent allowed key list and used when validate tx, int values are meaningless. 21 var enterpriseKeyDict = map[string]int{ 22 RPCPermissions: 1, 23 P2PWhite: 2, 24 P2PBlack: 3, 25 AccountWhite: 4, 26 } 27 28 type Conf struct { 29 On bool 30 Values []string 31 } 32 33 func (c *Conf) AppendValue(r string) { 34 if c.Values == nil { 35 c.Values = []string{} 36 } 37 c.Values = append(c.Values, r) 38 } 39 func (c *Conf) RemoveValue(r string) { 40 for i, v := range c.Values { 41 if v == r { 42 c.Values = append(c.Values[:i], c.Values[i+1:]...) 43 break 44 } 45 } 46 } 47 48 func (c *Conf) Validate(key []byte, context *EnterpriseContext) error { 49 if !c.On { 50 return nil 51 } 52 strKey := string(key) 53 switch strKey { 54 case RPCPermissions: 55 for _, v := range c.Values { 56 if strings.Contains(strings.ToUpper(strings.Split(v, ":")[1]), "W") { 57 return nil 58 } 59 } 60 return fmt.Errorf("the values of %s should have at least one write permission", strKey) 61 case AccountWhite: 62 for _, v := range context.Admins { 63 address := types.EncodeAddress(v) 64 if context.HasConfValue(address) { 65 return nil 66 } 67 } 68 return fmt.Errorf("the values of %s should have at least one admin address", strKey) 69 default: 70 return nil 71 } 72 return nil 73 } 74 75 // AccountStateReader is an interface for getting a enterprise account state. 76 type AccountStateReader interface { 77 GetEnterpriseAccountState() (*state.ContractState, error) 78 } 79 80 func GetConf(r AccountStateReader, key string) (*types.EnterpriseConfig, error) { 81 scs, err := r.GetEnterpriseAccountState() 82 if err != nil { 83 return nil, err 84 } 85 ret := &types.EnterpriseConfig{Key: key} 86 if strings.ToUpper(key) == "PERMISSIONS" { 87 for k, _ := range enterpriseKeyDict { 88 ret.Values = append(ret.Values, k) 89 } 90 } else { 91 conf, err := getConf(scs, []byte(key)) 92 if err != nil { 93 return nil, err 94 } 95 if conf != nil { 96 ret.On = conf.On 97 ret.Values = conf.Values 98 } 99 } 100 return ret, nil 101 } 102 103 func enableConf(scs *state.ContractState, key []byte, value bool) (*Conf, error) { 104 conf, err := getConf(scs, key) 105 if err != nil { 106 return nil, err 107 } 108 if conf != nil { 109 conf.On = value 110 } else { 111 conf = &Conf{On: value} 112 } 113 return conf, nil 114 } 115 116 func getConf(scs *state.ContractState, key []byte) (*Conf, error) { 117 data, err := scs.GetData(append(confPrefix, genKey(key)...)) 118 if err != nil || data == nil { 119 return nil, err 120 } 121 return deserializeConf(data), err 122 } 123 124 func setConfValues(scs *state.ContractState, key []byte, values []string) (*Conf, error) { 125 conf, err := getConf(scs, key) 126 if err != nil { 127 return nil, err 128 } 129 if conf != nil { 130 conf.Values = values 131 } else { 132 conf = &Conf{Values: values} 133 } 134 return conf, nil 135 } 136 137 func setConf(scs *state.ContractState, key []byte, conf *Conf) error { 138 return scs.SetData(append(confPrefix, genKey(key)...), serializeConf(conf)) 139 } 140 141 func serializeConf(c *Conf) []byte { 142 var ret []byte 143 if c.On { 144 ret = append(ret, 1) 145 } else { 146 ret = append(ret, 0) 147 } 148 for _, v := range c.Values { 149 ret = append(ret, '\\') 150 ret = append(ret, []byte(v)...) 151 } 152 return ret 153 } 154 155 func deserializeConf(data []byte) *Conf { 156 ret := &Conf{ 157 On: false, 158 Values: strings.Split(string(data), "\\")[1:], 159 } 160 if data[0] == 1 { 161 ret.On = true 162 } 163 return ret 164 } 165 166 func genKey(key []byte) []byte { 167 return []byte(strings.ToUpper(string(key))) 168 }