github.com/cheng762/platon-go@v1.8.17-0.20190529111256-7deff2d7be26/cmd/ctool/core/contractcmd.go (about) 1 package core 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "github.com/PlatONnetwork/PlatON-Go/common/hexutil" 7 "github.com/PlatONnetwork/PlatON-Go/rlp" 8 "gopkg.in/urfave/cli.v1" 9 "io/ioutil" 10 "time" 11 ) 12 13 var ( 14 DeployCmd = cli.Command{ 15 Name: "deploy", 16 Usage: "deploy a contract", 17 Action: deploy, 18 Flags: deployCmdFlags, 19 } 20 21 InvokeCmd = cli.Command{ 22 Name: "invoke", 23 Aliases: []string{"i"}, 24 Usage: "invoke contract function", 25 Action: invoke, 26 Flags: invokeCmdFlags, 27 } 28 ) 29 30 func deploy(c *cli.Context) error { 31 32 abiPath := c.String("abi") 33 codePath := c.String("code") 34 35 parseConfigJson(c.String(ConfigPathFlag.Name)) 36 err := DeployContract(abiPath, codePath) 37 38 if err != nil { 39 panic(fmt.Errorf("deploy contract error,%s", err.Error())) 40 } 41 return nil 42 } 43 44 func DeployContract(abiFilePath string, codeFilePath string) error { 45 var err error 46 47 abiBytes := parseFileToBytes(abiFilePath) 48 codeBytes := parseFileToBytes(codeFilePath) 49 50 param := [3][]byte{ 51 Int64ToBytes(deployContract), 52 codeBytes, 53 abiBytes, 54 } 55 paramBytes, err := rlp.EncodeToBytes(param) 56 if err != nil { 57 return fmt.Errorf("rlp encode error,%s", err.Error()) 58 } 59 60 deployParams := DeployParams{ 61 From: config.From, 62 GasPrice: config.GasPrice, 63 Gas: config.Gas, 64 Data: hexutil.Encode(paramBytes), 65 } 66 67 params := make([]interface{}, 1) 68 params[0] = deployParams 69 70 //paramJson, _ := json.Marshal(paramList) 71 //fmt.Printf("\n request json data:%s\n", string(paramJson)) 72 73 r, err := Send(params, "eth_sendTransaction") 74 75 //fmt.Printf("\nresponse json:%s\n", r) 76 77 resp := parseResponse(r) 78 79 fmt.Printf("\ntrasaction hash: %s\n", resp.Result) 80 81 // Get transaction receipt according to result 82 ch := make(chan string, 1) 83 go GetTransactionReceipt(resp.Result, ch) 84 85 // Getting receipt 86 select { 87 case address := <-ch: 88 fmt.Printf("contract address: %s\n", address) 89 case <-time.After(time.Second * 200): 90 fmt.Printf("get contract receipt timeout...more than 200 second.\n") 91 } 92 return err 93 94 } 95 96 func parseFileToBytes(file string) []byte { 97 bytes, err := ioutil.ReadFile(file) 98 if err != nil { 99 panic(fmt.Sprintf("parse file %s error,%s", file, err.Error())) 100 } 101 return bytes 102 } 103 104 func invoke(c *cli.Context) error { 105 addr := c.String("addr") 106 abiPath := c.String("abi") 107 funcParams := c.String("func") 108 txType := c.Int("type") 109 110 //param check 111 if abiPath == "" { 112 fmt.Printf("abi can't be empty!") 113 return nil 114 } 115 if addr == "" { 116 fmt.Printf("addr can't be empty!") 117 return nil 118 } 119 if funcParams == "" { 120 fmt.Printf("func can't be empty!") 121 return nil 122 } 123 parseConfigJson(c.String(ConfigPathFlag.Name)) 124 125 err := InvokeContract(addr, abiPath, funcParams, txType) 126 if err != nil { 127 panic(fmt.Errorf("invokeContract contract error,%s", err.Error())) 128 } 129 return nil 130 } 131 132 /** 133 134 */ 135 func InvokeContract(contractAddr string, abiPath string, funcParams string, txType int) error { 136 137 //Judging whether this contract exists or not 138 if !getContractByAddress(contractAddr) { 139 return fmt.Errorf("the contract address is not exist ...") 140 } 141 142 //parse the function and param 143 funcName, inputParams := GetFuncNameAndParams(funcParams) 144 145 //Judging whether this method exists or not 146 abiFunc, err := parseFuncFromAbi(abiPath, funcName) 147 if err != nil { 148 return err 149 } 150 151 if len(abiFunc.Inputs) != len(inputParams) { 152 return fmt.Errorf("incorrect number of parameters ,request=%d,get=%d\n", len(abiFunc.Inputs), len(inputParams)) 153 } 154 155 if txType == 0 { 156 txType = invokeContract 157 } 158 159 paramArr := [][]byte{ 160 Int64ToBytes(int64(txType)), 161 []byte(funcName), 162 } 163 164 for i, v := range inputParams { 165 input := abiFunc.Inputs[i] 166 p, e := StringConverter(v, input.Type) 167 if e != nil { 168 return fmt.Errorf("incorrect param type: %s,index:%d", v, i) 169 } 170 paramArr = append(paramArr, p) 171 } 172 173 paramBytes, e := rlp.EncodeToBytes(paramArr) 174 if e != nil { 175 return fmt.Errorf("rpl encode error,%s", e.Error()) 176 } 177 178 txParams := TxParams{ 179 From: config.From, 180 To: contractAddr, 181 GasPrice: config.GasPrice, 182 Gas: config.Gas, 183 Data: hexutil.Encode(paramBytes), 184 } 185 186 var r string 187 if abiFunc.Constant == "true" { 188 params := make([]interface{}, 2) 189 params[0] = txParams 190 params[1] = "latest" 191 192 paramJson, _ := json.Marshal(params) 193 fmt.Printf("\n request json data:%s \n", string(paramJson)) 194 r, err = Send(params, "eth_call") 195 } else { 196 params := make([]interface{}, 1) 197 params[0] = txParams 198 199 paramJson, _ := json.Marshal(params) 200 fmt.Printf("\n request json data:%s \n", string(paramJson)) 201 r, err = Send(params, "eth_sendTransaction") 202 } 203 204 fmt.Printf("\n response json:%s \n", r) 205 206 if err != nil { 207 return fmt.Errorf("send http post to invokeContract contract error,%s", e.Error()) 208 } 209 resp := parseResponse(r) 210 211 //parse the return type through adi 212 if abiFunc.Constant == "true" { 213 if len(abiFunc.Outputs) != 0 && abiFunc.Outputs[0].Type != "void" { 214 bytes, _ := hexutil.Decode(resp.Result) 215 result := BytesConverter(bytes, abiFunc.Outputs[0].Type) 216 fmt.Printf("\nresult: %v\n", result) 217 return nil 218 } 219 fmt.Printf("\n result: []\n") 220 } else { 221 fmt.Printf("\n trasaction hash: %s\n", resp.Result) 222 } 223 return nil 224 } 225 226 /** 227 Judging whether a contract exists through eth_getCode 228 */ 229 func getContractByAddress(addr string) bool { 230 231 params := []string{addr, "latest"} 232 r, err := Send(params, "eth_getCode") 233 if err != nil { 234 fmt.Printf("send http post to get contract address error ") 235 return false 236 } 237 238 var resp = Response{} 239 err = json.Unmarshal([]byte(r), &resp) 240 if err != nil { 241 fmt.Printf("parse eth_getCode result error ! \n %s", err.Error()) 242 return false 243 } 244 245 if resp.Error.Code != 0 { 246 fmt.Printf("eth_getCode error ,error:%v", resp.Error.Message) 247 return false 248 } 249 //fmt.Printf("trasaction hash: %s\n", resp.Result) 250 251 if resp.Result != "" && len(resp.Result) > 2 { 252 return true 253 } else { 254 return false 255 } 256 } 257 258 /* 259 Loop call to get transactionReceipt... until 200s timeout 260 */ 261 func GetTransactionReceipt(txHash string, ch chan string) { 262 var receipt = Receipt{} 263 var contractAddr string 264 for { 265 res, _ := Send([]string{txHash}, "eth_getTransactionReceipt") 266 e := json.Unmarshal([]byte(res), &receipt) 267 if e != nil { 268 panic(fmt.Sprintf("parse get receipt result error ! \n %s", e.Error())) 269 } 270 contractAddr = receipt.Result.ContractAddress 271 if contractAddr != "" { 272 ch <- contractAddr 273 break 274 } 275 } 276 }