// Copyright Fuzamei Corp. 2018 All Rights Reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package rpc import ( "encoding/hex" "time" "github.com/33cn/chain33/account" "github.com/33cn/chain33/client" "github.com/33cn/chain33/common" "github.com/33cn/chain33/common/address" "github.com/33cn/chain33/common/log/log15" "github.com/33cn/chain33/queue" ety "github.com/33cn/chain33/system/dapp/coins/types" "github.com/33cn/chain33/types" ) //提供系统rpc接口 var log = log15.New("module", "rpc") type channelClient struct { client.QueueProtocolAPI accountdb *account.DB } func (c *channelClient) Init(q queue.Client, api client.QueueProtocolAPI) { if api == nil { api, _ = client.New(q, nil) } c.QueueProtocolAPI = api c.accountdb = account.NewCoinsAccount() } func (c *channelClient) CreateRawTransaction(param *types.CreateTx) ([]byte, error) { if param == nil { log.Error("CreateRawTransaction", "Error", types.ErrInvalidParam) return nil, types.ErrInvalidParam } //因为历史原因,这里还是有部分token 的字段,但是没有依赖token dapp //未来这个调用可能会被废弃 execer := types.ExecName(ety.CoinsX) if param.IsToken { execer = types.ExecName("token") } return types.CallCreateTx(execer, "", param) } func (c *channelClient) CreateRawTxGroup(param *types.CreateTransactionGroup) ([]byte, error) { if param == nil || len(param.Txs) <= 1 { return nil, types.ErrTxGroupCountLessThanTwo } var transactions []*types.Transaction for _, t := range param.Txs { txByte, err := hex.DecodeString(t) if err != nil { return nil, err } var transaction types.Transaction err = types.Decode(txByte, &transaction) if err != nil { return nil, err } transactions = append(transactions, &transaction) } group, err := types.CreateTxGroup(transactions) if err != nil { return nil, err } txGroup := group.Tx() txHex := types.Encode(txGroup) return txHex, nil } func (c *channelClient) CreateNoBalanceTransaction(in *types.NoBalanceTx) (*types.Transaction, error) { txNone := &types.Transaction{Execer: []byte(types.ExecName(types.NoneX)), Payload: []byte("no-fee-transaction")} txNone.To = address.ExecAddress(string(txNone.Execer)) txNone, err := types.FormatTx(types.ExecName(types.NoneX), txNone) if err != nil { return nil, err } tx, err := decodeTx(in.TxHex) if err != nil { return nil, err } transactions := []*types.Transaction{txNone, tx} group, err := types.CreateTxGroup(transactions) if err != nil { return nil, err } err = group.Check(0, types.GInt("MinFee")) if err != nil { return nil, err } newtx := group.Tx() //如果可能要做签名 if in.PayAddr != "" || in.Privkey != "" { rawTx := hex.EncodeToString(types.Encode(newtx)) req := &types.ReqSignRawTx{Addr: in.PayAddr, Privkey: in.Privkey, Expire: in.Expire, TxHex: rawTx, Index: 1} signedTx, err := c.SignRawTx(req) if err != nil { return nil, err } return decodeTx(signedTx.TxHex) } return newtx, nil } func decodeTx(hexstr string) (*types.Transaction, error) { var tx types.Transaction data, err := hex.DecodeString(hexstr) if err != nil { return nil, err } err = types.Decode(data, &tx) if err != nil { return nil, err } return &tx, nil } func (c *channelClient) SendRawTransaction(param *types.SignedTx) (*types.Reply, error) { if param == nil { err := types.ErrInvalidParam log.Error("SendRawTransaction", "Error", err) return nil, err } var tx types.Transaction err := types.Decode(param.GetUnsign(), &tx) if err == nil { tx.Signature = &types.Signature{param.GetTy(), param.GetPubkey(), param.GetSign()} return c.SendTx(&tx) } return nil, err } func (c *channelClient) GetAddrOverview(parm *types.ReqAddr) (*types.AddrOverview, error) { err := address.CheckAddress(parm.Addr) if err != nil { return nil, types.ErrInvalidAddress } reply, err := c.QueueProtocolAPI.GetAddrOverview(parm) if err != nil { log.Error("GetAddrOverview", "Error", err.Error()) return nil, err } //获取地址账户的余额通过account模块 addrs := make([]string, 1) addrs[0] = parm.Addr accounts, err := c.accountdb.LoadAccounts(c.QueueProtocolAPI, addrs) if err != nil { log.Error("GetAddrOverview", "Error", err.Error()) return nil, err } if len(accounts) != 0 { reply.Balance = accounts[0].Balance } return reply, nil } func (c *channelClient) GetBalance(in *types.ReqBalance) ([]*types.Account, error) { return c.accountdb.GetBalance(c.QueueProtocolAPI, in) } func (c *channelClient) GetAllExecBalance(in *types.ReqAddr) (*types.AllExecBalance, error) { addr := in.Addr err := address.CheckAddress(addr) if err != nil { return nil, types.ErrInvalidAddress } var addrs []string addrs = append(addrs, addr) allBalance := &types.AllExecBalance{Addr: addr} for _, exec := range types.AllowUserExec { execer := string(exec) params := &types.ReqBalance{ Addresses: addrs, Execer: execer, } res, err := c.GetBalance(params) if err != nil { continue } if len(res) < 1 { continue } acc := res[0] if acc.Balance == 0 && acc.Frozen == 0 { continue } execAcc := &types.ExecAccount{Execer: execer, Account: acc} allBalance.ExecAccount = append(allBalance.ExecAccount, execAcc) } return allBalance, nil } func (c *channelClient) GetTotalCoins(in *types.ReqGetTotalCoins) (*types.ReplyGetTotalCoins, error) { //获取地址账户的余额通过account模块 resp, err := c.accountdb.GetTotalCoins(c.QueueProtocolAPI, in) if err != nil { return nil, err } return resp, nil } func (c *channelClient) DecodeRawTransaction(param *types.ReqDecodeRawTransaction) (*types.Transaction, error) { var tx types.Transaction bytes, err := common.FromHex(param.TxHex) if err != nil { return nil, err } err = types.Decode(bytes, &tx) if err != nil { return nil, err } return &tx, nil } func (c *channelClient) GetTimeStatus() (*types.TimeStatus, error) { ntpTime := common.GetRealTimeRetry(types.NtpHosts, 10) local := types.Now() if ntpTime.IsZero() { return &types.TimeStatus{NtpTime: "", LocalTime: local.Format("2006-01-02 15:04:05"), Diff: 0}, nil } diff := local.Sub(ntpTime) / time.Second 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 }