github.com/turingchain2020/turingchain@v1.1.21/rpc/client.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package rpc turingchain RPC模块包含JSONRpc以及grpc 6 package rpc 7 8 import ( 9 "encoding/hex" 10 "time" 11 12 "github.com/turingchain2020/turingchain/account" 13 "github.com/turingchain2020/turingchain/client" 14 "github.com/turingchain2020/turingchain/common" 15 "github.com/turingchain2020/turingchain/common/address" 16 "github.com/turingchain2020/turingchain/common/log/log15" 17 "github.com/turingchain2020/turingchain/queue" 18 ety "github.com/turingchain2020/turingchain/system/dapp/coins/types" 19 "github.com/turingchain2020/turingchain/types" 20 ) 21 22 var log = log15.New("module", "rpc") 23 24 type channelClient struct { 25 client.QueueProtocolAPI 26 accountdb *account.DB 27 } 28 29 // Init channel client 30 func (c *channelClient) Init(q queue.Client, api client.QueueProtocolAPI) { 31 if api == nil { 32 var err error 33 api, err = client.New(q, nil) 34 if err != nil { 35 panic(err) 36 } 37 } 38 c.QueueProtocolAPI = api 39 c.accountdb = account.NewCoinsAccount(q.GetConfig()) 40 } 41 42 // CreateRawTransaction create rawtransaction 43 func (c *channelClient) CreateRawTransaction(param *types.CreateTx) ([]byte, error) { 44 if param == nil { 45 log.Error("CreateRawTransaction", "Error", types.ErrInvalidParam) 46 return nil, types.ErrInvalidParam 47 } 48 //构建交易时to地址不为空时需要检测地址的合法性 49 if param.GetTo() != "" { 50 if err := address.CheckAddress(param.GetTo()); err != nil { 51 return nil, types.ErrInvalidAddress 52 } 53 } 54 //因为历史原因,这里还是有部分token 的字段,但是没有依赖token dapp 55 //未来这个调用可能会被废弃 56 types.AssertConfig(c.QueueProtocolAPI) 57 cfg := c.QueueProtocolAPI.GetConfig() 58 execer := cfg.ExecName(ety.CoinsX) 59 if param.IsToken { 60 execer = cfg.ExecName("token") 61 } 62 if param.Execer != "" { 63 execer = param.Execer 64 } 65 reply, err := types.CallCreateTx(cfg, execer, "", param) 66 if err != nil { 67 return nil, err 68 } 69 70 //add tx fee setting 71 tx := &types.Transaction{} 72 err = types.Decode(reply, tx) 73 if err != nil { 74 return nil, err 75 } 76 tx.Fee = param.Fee 77 //set proper fee if zero fee 78 if tx.Fee <= 0 { 79 proper, err := c.GetProperFee(nil) 80 if err != nil { 81 return nil, err 82 } 83 fee, err := tx.GetRealFee(proper.GetProperFee()) 84 if err != nil { 85 return nil, err 86 } 87 tx.Fee = fee 88 } 89 90 return types.Encode(tx), nil 91 } 92 93 func (c *channelClient) ReWriteRawTx(param *types.ReWriteRawTx) ([]byte, error) { 94 types.AssertConfig(c.QueueProtocolAPI) 95 cfg := c.QueueProtocolAPI.GetConfig() 96 if param == nil || param.Tx == "" { 97 log.Error("ReWriteRawTx", "Error", types.ErrInvalidParam) 98 return nil, types.ErrInvalidParam 99 } 100 101 tx, err := decodeTx(param.Tx) 102 if err != nil { 103 return nil, err 104 } 105 if param.To != "" { 106 tx.To = param.To 107 } 108 if param.Fee != 0 && param.Fee > tx.Fee { 109 tx.Fee = param.Fee 110 } 111 var expire int64 112 if param.Expire != "" { 113 expire, err = types.ParseExpire(param.Expire) 114 if err != nil { 115 return nil, err 116 } 117 tx.SetExpire(cfg, time.Duration(expire)) 118 } 119 group, err := tx.GetTxGroup() 120 if err != nil { 121 return nil, err 122 } 123 124 //单笔交易直接返回 125 if group == nil { 126 txHex := types.Encode(tx) 127 return txHex, nil 128 } 129 130 //交易组的处理 131 index := param.Index 132 if int(index) > len(group.GetTxs()) { 133 return nil, types.ErrIndex 134 } 135 136 //修改交易组中所有成员交易 137 if index <= 0 { 138 if param.Fee != 0 && param.Fee > group.Txs[0].Fee { 139 group.Txs[0].Fee = param.Fee 140 } 141 if param.Expire != "" { 142 for i := 0; i < len(group.Txs); i++ { 143 group.SetExpire(cfg, i, time.Duration(expire)) 144 } 145 } 146 group.RebuiltGroup() 147 grouptx := group.Tx() 148 txHex := types.Encode(grouptx) 149 return txHex, nil 150 } 151 //修改交易组中指定成员交易 152 index-- 153 if param.Fee != 0 && index == 0 && param.Fee > group.Txs[0].Fee { 154 group.Txs[0].Fee = param.Fee 155 } 156 if param.Expire != "" { 157 group.SetExpire(cfg, int(index), time.Duration(expire)) 158 } 159 group.RebuiltGroup() 160 grouptx := group.Tx() 161 txHex := types.Encode(grouptx) 162 return txHex, nil 163 } 164 165 // CreateRawTxGroup create rawtransaction for group 166 func (c *channelClient) CreateRawTxGroup(param *types.CreateTransactionGroup) ([]byte, error) { 167 types.AssertConfig(c.QueueProtocolAPI) 168 cfg := c.QueueProtocolAPI.GetConfig() 169 if param == nil || len(param.Txs) <= 1 { 170 return nil, types.ErrTxGroupCountLessThanTwo 171 } 172 var transactions []*types.Transaction 173 for _, t := range param.Txs { 174 txByte, err := common.FromHex(t) 175 if err != nil { 176 return nil, err 177 } 178 var transaction types.Transaction 179 err = types.Decode(txByte, &transaction) 180 if err != nil { 181 return nil, err 182 } 183 transactions = append(transactions, &transaction) 184 } 185 feeRate := cfg.GetMinTxFeeRate() 186 //get proper fee rate 187 proper, err := c.GetProperFee(nil) 188 if err != nil { 189 log.Error("CreateNoBalance", "GetProperFeeErr", err) 190 return nil, err 191 } 192 if proper.GetProperFee() > feeRate { 193 feeRate = proper.ProperFee 194 } 195 group, err := types.CreateTxGroup(transactions, feeRate) 196 if err != nil { 197 return nil, err 198 } 199 200 txGroup := group.Tx() 201 txHex := types.Encode(txGroup) 202 return txHex, nil 203 } 204 205 // CreateNoBalanceTxs create the multiple transaction with no balance 206 // 实际使用的时候要注意,一般情况下,不要传递 private key 到服务器端,除非是本地localhost 的服务。 207 func (c *channelClient) CreateNoBalanceTxs(in *types.NoBalanceTxs) (*types.Transaction, error) { 208 types.AssertConfig(c.QueueProtocolAPI) 209 cfg := c.QueueProtocolAPI.GetConfig() 210 txNone := &types.Transaction{Execer: []byte(cfg.ExecName(types.NoneX)), Payload: []byte("no-fee-transaction")} 211 txNone.To = address.ExecAddress(string(txNone.Execer)) 212 txNone, err := types.FormatTx(cfg, cfg.ExecName(types.NoneX), txNone) 213 if err != nil { 214 return nil, err 215 } 216 //不设置时默认为永不超时 217 if in.Expire == "" { 218 in.Expire = "0" 219 } 220 expire, err := types.ParseExpire(in.Expire) 221 if err != nil { 222 return nil, err 223 } 224 //交易组只需要设置单笔交易超时 225 txNone.SetExpire(cfg, time.Duration(expire)) 226 isParaTx := false 227 transactions := []*types.Transaction{txNone} 228 for _, txhex := range in.TxHexs { 229 tx, err := decodeTx(txhex) 230 if err != nil { 231 return nil, err 232 } 233 if types.IsParaExecName(string(tx.GetExecer())) { 234 isParaTx = true 235 } 236 transactions = append(transactions, tx) 237 } 238 239 //平行链下不允许设置高度作为过期判定, issue#706 240 if expire > 0 && expire <= types.ExpireBound && isParaTx { 241 return nil, types.ErrInvalidExpire 242 } 243 244 feeRate := cfg.GetMinTxFeeRate() 245 //get proper fee rate 246 proper, err := c.GetProperFee(nil) 247 if err != nil { 248 log.Error("CreateNoBalance", "GetProperFeeErr", err) 249 return nil, err 250 } 251 if proper.GetProperFee() > feeRate { 252 feeRate = proper.ProperFee 253 } 254 group, err := types.CreateTxGroup(transactions, feeRate) 255 if err != nil { 256 return nil, err 257 } 258 err = group.Check(cfg, 0, cfg.GetMinTxFeeRate(), cfg.GetMaxTxFee()) 259 if err != nil { 260 return nil, err 261 } 262 263 newtx := group.Tx() 264 //如果可能要做签名 265 if in.PayAddr != "" || in.Privkey != "" { 266 rawTx := hex.EncodeToString(types.Encode(newtx)) 267 req := &types.ReqSignRawTx{Addr: in.PayAddr, Privkey: in.Privkey, Expire: in.Expire, TxHex: rawTx, Index: 1} 268 signedTx, err := c.ExecWalletFunc("wallet", "SignRawTx", req) 269 if err != nil { 270 return nil, err 271 } 272 return decodeTx(signedTx.(*types.ReplySignRawTx).TxHex) 273 } 274 return newtx, nil 275 } 276 277 func decodeTx(hexstr string) (*types.Transaction, error) { 278 var tx types.Transaction 279 data, err := common.FromHex(hexstr) 280 if err != nil { 281 return nil, err 282 } 283 err = types.Decode(data, &tx) 284 if err != nil { 285 return nil, err 286 } 287 return &tx, nil 288 } 289 290 // GetAddrOverview get overview of address 291 func (c *channelClient) GetAddrOverview(parm *types.ReqAddr) (*types.AddrOverview, error) { 292 err := address.CheckAddress(parm.Addr) 293 if err != nil { 294 return nil, types.ErrInvalidAddress 295 } 296 reply, err := c.QueueProtocolAPI.GetAddrOverview(parm) 297 if err != nil { 298 log.Error("GetAddrOverview", "Error", err.Error()) 299 return nil, err 300 } 301 //获取地址账户的余额通过account模块 302 addrs := make([]string, 1) 303 addrs[0] = parm.Addr 304 accounts, err := c.accountdb.LoadAccounts(c.QueueProtocolAPI, addrs) 305 if err != nil { 306 log.Error("GetAddrOverview", "Error", err.Error()) 307 return nil, err 308 } 309 if len(accounts) != 0 { 310 reply.Balance = accounts[0].Balance 311 } 312 return reply, nil 313 } 314 315 // GetBalance get balance 316 func (c *channelClient) GetBalance(in *types.ReqBalance) ([]*types.Account, error) { 317 // in.AssetExec & in.AssetSymbol 新增参数, 318 // 不填时兼容原来的调用 319 if in.AssetExec == "" || in.AssetSymbol == "" { 320 in.AssetSymbol = "trc" 321 in.AssetExec = "coins" 322 return c.accountdb.GetBalance(c.QueueProtocolAPI, in) 323 } 324 325 acc, err := account.NewAccountDB(c.QueueProtocolAPI.GetConfig(), in.AssetExec, in.AssetSymbol, nil) 326 if err != nil { 327 log.Error("GetBalance", "Error", err.Error()) 328 return nil, err 329 } 330 return acc.GetBalance(c.QueueProtocolAPI, in) 331 } 332 333 // GetAllExecBalance get balance of exec 334 func (c *channelClient) GetAllExecBalance(in *types.ReqAllExecBalance) (*types.AllExecBalance, error) { 335 types.AssertConfig(c.QueueProtocolAPI) 336 cfg := c.QueueProtocolAPI.GetConfig() 337 addr := in.Addr 338 err := address.CheckAddress(addr) 339 if err != nil { 340 if err = address.CheckMultiSignAddress(addr); err != nil { 341 return nil, types.ErrInvalidAddress 342 } 343 } 344 var addrs []string 345 addrs = append(addrs, addr) 346 allBalance := &types.AllExecBalance{Addr: addr} 347 for _, exec := range types.AllowUserExec { 348 execer := cfg.ExecName(string(exec)) 349 params := &types.ReqBalance{ 350 Addresses: addrs, 351 Execer: execer, 352 StateHash: in.StateHash, 353 AssetExec: in.AssetExec, 354 AssetSymbol: in.AssetSymbol, 355 } 356 res, err := c.GetBalance(params) 357 if err != nil { 358 continue 359 } 360 if len(res) < 1 { 361 continue 362 } 363 acc := res[0] 364 if acc.Balance == 0 && acc.Frozen == 0 { 365 continue 366 } 367 execAcc := &types.ExecAccount{Execer: execer, Account: acc} 368 allBalance.ExecAccount = append(allBalance.ExecAccount, execAcc) 369 } 370 return allBalance, nil 371 } 372 373 // GetTotalCoins get total of coins 374 func (c *channelClient) GetTotalCoins(in *types.ReqGetTotalCoins) (*types.ReplyGetTotalCoins, error) { 375 //获取地址账户的余额通过account模块 376 resp, err := c.accountdb.GetTotalCoins(c.QueueProtocolAPI, in) 377 if err != nil { 378 return nil, err 379 } 380 return resp, nil 381 } 382 383 // DecodeRawTransaction decode rawtransaction 384 func (c *channelClient) DecodeRawTransaction(param *types.ReqDecodeRawTransaction) (*types.Transaction, error) { 385 var tx types.Transaction 386 bytes, err := common.FromHex(param.TxHex) 387 if err != nil { 388 return nil, err 389 } 390 err = types.Decode(bytes, &tx) 391 if err != nil { 392 return nil, err 393 } 394 return &tx, nil 395 } 396 397 // GetTimeStatus get status of time 398 func (c *channelClient) GetTimeStatus() (*types.TimeStatus, error) { 399 ntpTime := common.GetRealTimeRetry(c.GetConfig().GetModuleConfig().NtpHosts, 2) 400 local := time.Now() 401 if ntpTime.IsZero() { 402 return &types.TimeStatus{NtpTime: "", LocalTime: local.Format("2006-01-02 15:04:05"), Diff: 0}, nil 403 } 404 diff := local.Sub(ntpTime) / time.Second 405 return &types.TimeStatus{NtpTime: ntpTime.Format("2006-01-02 15:04:05"), LocalTime: local.Format("2006-01-02 15:04:05"), Diff: int64(diff)}, nil 406 } 407 408 // GetExecBalance get balance with exec by channelclient 409 func (c *channelClient) GetExecBalance(in *types.ReqGetExecBalance) (*types.ReplyGetExecBalance, error) { 410 //通过account模块获取地址账户在合约中的余额 411 resp, err := c.accountdb.GetExecBalance(c.QueueProtocolAPI, in) 412 if err != nil { 413 return nil, err 414 } 415 return resp, nil 416 }