github.com/aergoio/aergo@v1.3.1/contract/enterprise/changecluster.go (about) 1 package enterprise 2 3 import ( 4 "fmt" 5 "github.com/aergoio/aergo/types" 6 "reflect" 7 "strconv" 8 ) 9 10 type CcArgument map[string]interface{} 11 12 const ( 13 CmdMembershipAdd = "add" 14 CmdMembershipRemove = "remove" 15 16 CCCommand = "command" 17 MemberAttrName = "name" 18 MemberAttrAddress = "address" 19 MemberAttrPeerID = "peerid" 20 MemberAttrID = "id" 21 ) 22 23 /* 24 var ( 25 ConfChangeState_name = map[ConfChangeState]string{ 26 0: "Proposed", 27 1: "Saved", 28 2: "Applied", 29 } 30 )*/ 31 32 func ValidateChangeCluster(ci types.CallInfo, blockNo types.BlockNo) (interface{}, error) { 33 var ( 34 ccArg CcArgument 35 ok bool 36 err error 37 changeReq *types.MembershipChange 38 ) 39 40 if len(ci.Args) != 1 { //args[0] : map{ "command": "add", "name:", "address:", "peerid:", "id:"} 41 return nil, fmt.Errorf("invalid arguments in payload for ChangeCluster: %s", ci.Args) 42 } 43 44 ccArg, ok = ci.Args[0].(map[string]interface{}) 45 if !ok { 46 return nil, fmt.Errorf("invalid argument in payload for ChangeCluster(map[string]interface{}) : argument=%v", reflect.TypeOf(ci.Args[0])) 47 } 48 49 if changeReq, err = ccArg.parse(); err != nil { 50 return nil, err 51 } 52 53 changeReq.RequestID = blockNo 54 55 return changeReq, nil 56 } 57 58 func (cc CcArgument) get(key string) (string, error) { 59 var ( 60 val interface{} 61 valStr string 62 ok bool 63 ) 64 65 if val, ok = cc[key]; !ok { 66 return "", fmt.Errorf("invalid ChangeCluster argument: not exist %s", key) 67 } 68 69 if valStr, ok = val.(string); !ok { 70 return "", fmt.Errorf("invalid ChangeCluster argument: not string value(%v)", reflect.TypeOf(val)) 71 } 72 73 return valStr, nil 74 } 75 76 func (cc CcArgument) getUint64(key string) (uint64, error) { 77 var ( 78 val interface{} 79 valUint float64 80 ok bool 81 ) 82 83 if val, ok = cc[key]; !ok { 84 return 0, fmt.Errorf("invalid ChangeCluster argument: not exist %s", key) 85 } 86 87 if valUint, ok = val.(float64); !ok { 88 return 0, fmt.Errorf("invalid ChangeCluster argument: not uint64(%v)", reflect.TypeOf(val)) 89 } 90 91 return uint64(valUint), nil 92 } 93 94 func (cc CcArgument) parse() (*types.MembershipChange, error) { 95 var ( 96 cmd, name, address, peeridStr, idStr string 97 id uint64 98 err error 99 mChange types.MembershipChange 100 peerID types.PeerID 101 ) 102 103 if cmd, err = cc.get(CCCommand); err != nil { 104 return nil, err 105 } 106 107 switch cmd { 108 case CmdMembershipAdd: 109 mChange.Type = types.MembershipChangeType_ADD_MEMBER 110 111 if name, err = cc.get(MemberAttrName); err != nil { 112 return nil, err 113 } 114 115 if address, err = cc.get(MemberAttrAddress); err != nil { 116 return nil, err 117 } 118 119 if peeridStr, err = cc.get(MemberAttrPeerID); err != nil { 120 return nil, err 121 } 122 123 peerID, err = types.IDB58Decode(peeridStr) 124 if err != nil { 125 return nil, fmt.Errorf("invalid ChangeCluster argument: can't decode peerid string(%s)", peeridStr) 126 } 127 128 if _, err := types.ParseMultiaddrWithResolve(address); err != nil { 129 return nil, fmt.Errorf("invalid ChangeCluster argument: %s", err.Error()) 130 } 131 132 case CmdMembershipRemove: 133 mChange.Type = types.MembershipChangeType_REMOVE_MEMBER 134 135 if idStr, err = cc.get(MemberAttrID); err != nil { 136 return nil, err 137 } 138 139 if id, err = strconv.ParseUint(idStr, 16, 64); err != nil { 140 return nil, fmt.Errorf("invalid ChangeCluster argument: invalid id %s. ID must be a string in hexadecial format(ex:dd44cf1a06727dc5)", idStr) 141 } 142 143 default: 144 return nil, fmt.Errorf("invalid ChangeCluster argument: invalid command %s", cmd) 145 } 146 147 mChange.Attr = &types.MemberAttr{Name: name, Address: address, PeerID: []byte(peerID), ID: id} 148 149 return &mChange, nil 150 }