github.com/aergoio/aergo@v1.3.1/contract/enterprise/execute.go (about) 1 package enterprise 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "strings" 9 10 "github.com/aergoio/aergo-lib/log" 11 "github.com/aergoio/aergo/consensus" 12 13 "github.com/aergoio/aergo/state" 14 "github.com/aergoio/aergo/types" 15 ) 16 17 var ( 18 entLogger *log.Logger 19 20 ErrNotSupportedMethod = errors.New("Not supported Enterprise Tx") 21 ErrTxEnterpriseAlreadyIncludeChangeCluster = errors.New("Enterprise Tx of Change cluster type already included in the block") 22 ) 23 24 type EnterpriseContext struct { 25 Call *types.CallInfo 26 Args []string 27 ArgsAny []interface{} 28 Admins [][]byte 29 Conf *Conf 30 } 31 32 func init() { 33 entLogger = log.NewLogger("enterprise") 34 } 35 36 func (e *EnterpriseContext) IsAdminExist(addr []byte) bool { 37 for _, a := range e.Admins { 38 if bytes.Equal(a, addr) { 39 return true 40 } 41 } 42 return false 43 } 44 45 func (e *EnterpriseContext) HasConfValue(value string) bool { 46 if e.Conf != nil { 47 for _, v := range e.Conf.Values { 48 if v == value { 49 return true 50 } 51 } 52 } 53 return false 54 } 55 56 func ExecuteEnterpriseTx(bs *state.BlockState, ccc consensus.ChainConsensusCluster, scs *state.ContractState, txBody *types.TxBody, 57 sender, receiver *state.V, blockNo types.BlockNo) ([]*types.Event, error) { 58 59 context, err := ValidateEnterpriseTx(txBody, sender, scs, blockNo) 60 if err != nil { 61 return nil, err 62 } 63 var events []*types.Event 64 switch context.Call.Name { 65 case AppendAdmin: 66 requestAddress := types.ToAddress(context.Args[0]) 67 err := setAdmins(scs, 68 append(context.Admins, requestAddress)) 69 if err != nil { 70 return nil, err 71 } 72 jsonArgs, err := json.Marshal(context.Args[0]) 73 if err != nil { 74 return nil, err 75 } 76 events = append(events, &types.Event{ 77 ContractAddress: receiver.ID(), 78 EventName: "Append ADMIN", 79 EventIdx: 0, 80 JsonArgs: string(jsonArgs), 81 }) 82 case RemoveAdmin: 83 for i, v := range context.Admins { 84 if bytes.Equal(v, types.ToAddress(context.Args[0])) { 85 context.Admins = append(context.Admins[:i], context.Admins[i+1:]...) 86 break 87 } 88 } 89 err := setAdmins(scs, context.Admins) 90 if err != nil { 91 return nil, err 92 } 93 jsonArgs, err := json.Marshal(context.Args[0]) 94 if err != nil { 95 return nil, err 96 } 97 events = append(events, &types.Event{ 98 ContractAddress: receiver.ID(), 99 EventName: "Remove ADMIN", 100 EventIdx: 0, 101 JsonArgs: string(jsonArgs), 102 }) 103 case SetConf, AppendConf, RemoveConf: 104 key := context.Args[0] 105 err = setConf(scs, []byte(key), context.Conf) 106 if err != nil { 107 return nil, err 108 } 109 events, err = createSetEvent(receiver.ID(), key, context.Conf.Values) 110 if err != nil { 111 return nil, err 112 } 113 case EnableConf: 114 key := context.Args[0] 115 err = setConf(scs, []byte(key), context.Conf) 116 if err != nil { 117 return nil, err 118 } 119 jsonArgs, err := json.Marshal(context.Call.Args[1]) 120 if err != nil { 121 return nil, err 122 } 123 events = append(events, &types.Event{ 124 ContractAddress: receiver.ID(), 125 EventName: "Enable " + strings.ToUpper(string(key)), 126 EventIdx: 0, 127 JsonArgs: string(jsonArgs), 128 }) 129 case ChangeCluster: 130 if bs.CCProposal != nil { 131 return nil, ErrTxEnterpriseAlreadyIncludeChangeCluster 132 } 133 134 ccReq, ok := context.ArgsAny[0].(*types.MembershipChange) 135 if !ok { 136 return nil, fmt.Errorf("invalid argument of cluster change request") 137 } 138 139 var ( 140 ccChange *consensus.ConfChangePropose 141 err error 142 ) 143 144 // MakeConfChangeProposal can make different results depending on the raft status. therefore the result shouldn not be written on receipt 145 if ccChange, err = ccc.MakeConfChangeProposal(ccReq); err != nil { 146 if err != consensus.ErrorMembershipChangeSkip { 147 entLogger.Error().Str("cluster change", ccReq.ToString()).Err(err).Msg("Enterprise tx: failed to make cluster change proposal") 148 } else { 149 entLogger.Info().Str("cluster change", ccReq.ToString()).Msg("Enterprise tx: skipped since this node is not leader") 150 } 151 } else { 152 bs.CCProposal = ccChange 153 } 154 155 /* 156 jsonArgs, err := json.Marshal(context.Call.Args[0]) 157 if err != nil { 158 return nil, err 159 } 160 161 entLogger.Debug().Str("jsonarg", string(jsonArgs)).Msg("make event") 162 163 events = append(events, &types.Event{ 164 ContractAddress: []byte(types.AergoEnterprise), 165 EventName: "ChangeCluster ", 166 EventIdx: 0, 167 JsonArgs: string(jsonArgs), 168 }) 169 */ 170 default: 171 return nil, fmt.Errorf("unsupported call in enterprise contract") 172 } 173 return events, nil 174 } 175 176 func createSetEvent(addr []byte, name string, v []string) ([]*types.Event, error) { 177 jsonArgs, err := json.Marshal(v) 178 if err != nil { 179 return nil, err 180 } 181 return []*types.Event{ 182 &types.Event{ 183 ContractAddress: addr, 184 EventName: "Set " + strings.ToUpper(name), 185 EventIdx: 0, 186 JsonArgs: string(jsonArgs), 187 }, 188 }, nil 189 }