Commit 2c249090 authored by 张振华's avatar 张振华

Merge branch 'master' into guess

parents 335380b0 e26a5b79
......@@ -33,6 +33,8 @@ const (
delAct int64 = 2 //reference blockstore.go, del para block action
paraCrossTxCount = 2 //current only support 2 txs for cross
minBlockNum = 6 //min block number startHeight before lastHeight in mainchain
)
var (
......@@ -40,7 +42,6 @@ var (
grpcSite = "localhost:8802"
genesisBlockTime int64 = 1514533390
startHeight int64 //parachain sync from startHeight in mainchain
searchSeq int64 //start sequence to search startHeight in mainchain
blockSec int64 = 5 //write block interval, second
emptyBlockInterval int64 = 4 //write empty block every interval blocks in mainchain
zeroHash [32]byte
......@@ -75,7 +76,6 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
}
if cfg.StartHeight > 0 {
startHeight = cfg.StartHeight
searchSeq = calcSearchseq(cfg.StartHeight)
}
if cfg.WriteBlockSeconds > 0 {
blockSec = cfg.WriteBlockSeconds
......@@ -139,13 +139,6 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
return para
}
func calcSearchseq(height int64) int64 {
if height < 1000 {
return 0
}
return height - 1000
}
//para 不检查任何的交易
func (client *client) CheckBlock(parent *types.Block, current *types.BlockDetail) error {
err := checkMinerTx(current)
......@@ -179,10 +172,7 @@ func (client *client) InitBlock() {
}
if block == nil {
startSeq := int64(0)
if searchSeq > 0 {
startSeq = client.GetSeqByHeightOnMain(startHeight, searchSeq)
}
startSeq := client.GetStartSeq(startHeight)
// 创世区块
newblock := &types.Block{}
newblock.Height = 0
......@@ -191,37 +181,47 @@ func (client *client) InitBlock() {
tx := client.CreateGenesisTx()
newblock.Txs = tx
newblock.TxHash = merkle.CalcMerkleRoot(newblock.Txs)
client.WriteBlock(zeroHash[:], newblock, startSeq-int64(1))
client.WriteBlock(zeroHash[:], newblock, startSeq-1)
} else {
client.SetCurrentBlock(block)
}
}
func (client *client) GetSeqByHeightOnMain(height int64, originSeq int64) int64 {
lastSeq, err := client.GetLastSeqOnMainChain()
plog.Info("Searching for the sequence", "heightOnMain", height, "searchSeq", searchSeq, "lastSeq", lastSeq)
// GetStartSeq get startSeq in mainchain
func (client *client) GetStartSeq(height int64) int64 {
if height == 0 {
return 0
}
lastHeight, err := client.GetLastHeightOnMainChain()
if err != nil {
panic(err)
}
hint := time.NewTicker(10 * time.Second)
defer hint.Stop()
for originSeq <= lastSeq {
if lastHeight < height {
panic(fmt.Sprintf("lastHeight(%d) less than startHeight(%d) in mainchain", lastHeight, height))
}
hint := time.NewTicker(5 * time.Second)
for lastHeight < height+minBlockNum {
select {
case <-hint.C:
plog.Info("Still Searching......", "searchAtSeq", originSeq, "lastSeq", lastSeq)
plog.Info("Waiting lastHeight increase......", "lastHeight", lastHeight, "startHeight", height)
default:
blockDetail, seqTy, err := client.GetBlockOnMainBySeq(originSeq)
lastHeight, err = client.GetLastHeightOnMainChain()
if err != nil {
panic(err)
}
if blockDetail.Block.Height == height && seqTy == addAct {
plog.Info("the target sequence in mainchain", "heightOnMain", height, "targetSeq", originSeq)
return originSeq
}
originSeq++
time.Sleep(time.Second)
}
}
panic("Main chain has not reached the height currently")
hint.Stop()
plog.Info(fmt.Sprintf("lastHeight more than %d blocks after startHeight", minBlockNum), "lastHeight", lastHeight, "startHeight", height)
seq, err := client.GetSeqByHeightOnMainChain(height)
if err != nil {
panic(err)
}
plog.Info("the start sequence in mainchain", "startHeight", height, "startSeq", seq)
return seq
}
func (client *client) CreateGenesisTx() (ret []*types.Transaction) {
......@@ -357,6 +357,15 @@ func (client *client) getLastBlockInfo() (int64, *types.Block, []byte, int64, er
}
func (client *client) GetLastHeightOnMainChain() (int64, error) {
header, err := client.grpcClient.GetLastHeader(context.Background(), &types.ReqNil{})
if err != nil {
plog.Error("GetLastHeightOnMainChain", "Error", err.Error())
return -1, err
}
return header.Height, nil
}
func (client *client) GetLastSeqOnMainChain() (int64, error) {
seq, err := client.grpcClient.GetLastBlockSequence(context.Background(), &types.ReqNil{})
if err != nil {
......@@ -367,6 +376,24 @@ func (client *client) GetLastSeqOnMainChain() (int64, error) {
return seq.Data, nil
}
func (client *client) GetSeqByHeightOnMainChain(height int64) (int64, error) {
hash, err := client.GetHashByHeightOnMainChain(height)
if err != nil {
return -1, err
}
seq, err := client.GetSeqByHashOnMainChain(hash)
return seq, err
}
func (client *client) GetHashByHeightOnMainChain(height int64) ([]byte, error) {
reply, err := client.grpcClient.GetBlockHash(context.Background(), &types.ReqInt{Height: height})
if err != nil {
plog.Error("GetHashByHeightOnMainChain", "Error", err.Error())
return nil, err
}
return reply.Hash, nil
}
func (client *client) GetSeqByHashOnMainChain(hash []byte) (int64, error) {
seq, err := client.grpcClient.GetSequenceByHash(context.Background(), &types.ReqHash{Hash: hash})
if err != nil {
......@@ -465,7 +492,6 @@ func (client *client) RequestTx(currSeq int64, preMainBlockHash []byte) ([]*type
//lastSeq = currSeq-1, main node not update
if lastSeq+1 == currSeq {
plog.Debug("Waiting new sequence from main chain")
time.Sleep(time.Second * time.Duration(blockSec*2))
return nil, nil, -1, paracross.ErrParaWaitingNewSeq
}
......@@ -596,15 +622,16 @@ func (client *client) CreateBlock() {
txs, blockOnMain, seqTy, err := client.RequestTx(currSeq, lastSeqMainHash)
if err != nil {
incSeqFlag = false
if err == paracross.ErrParaCurHashNotMatch {
newSeq, newSeqMainHash, err := client.switchHashMatchedBlock(currSeq)
if err == nil {
currSeq = newSeq
lastSeqMainHash = newSeqMainHash
continue
}
}
incSeqFlag = false
time.Sleep(time.Second)
time.Sleep(time.Second * time.Duration(blockSec))
continue
}
......
......@@ -92,6 +92,9 @@ func (s *suiteParaCommitMsg) initEnv(cfg *types.Config, sub *types.ConfigSubModu
ret := &types.Reply{IsOk: true, Msg: data}
s.grpcCli.On("QueryChain", mock.Anything, mock.Anything).Return(ret, nil).Maybe()
s.grpcCli.On("SendTransaction", mock.Anything, mock.Anything).Return(reply, nil).Maybe()
s.grpcCli.On("GetLastHeader", mock.Anything, mock.Anything).Return(&types.Header{Height: cfg.Consensus.StartHeight + minBlockNum}, nil).Maybe()
s.grpcCli.On("GetBlockHash", mock.Anything, mock.Anything).Return(&types.ReplyHash{Hash: []byte("1")}, nil).Maybe()
s.grpcCli.On("GetSequenceByHash", mock.Anything, mock.Anything).Return(&types.Int64{Data: cfg.Consensus.StartHeight}, nil).Maybe()
s.para.grpcClient = s.grpcCli
s.para.SetQueueClient(q.Client())
......
......@@ -58,7 +58,7 @@ func (s *suiteParaClient) initEnv(cfg *types.Config, sub *types.ConfigSubModule)
s.store = store.New(cfg.Store, sub.Store)
s.store.SetQueueClient(q.Client())
cfg.Consensus.StartHeight = 0
//cfg.Consensus.StartHeight = 0
cfg.Consensus.EmptyBlockInterval = 1
s.para = New(cfg.Consensus, sub.Consensus["para"]).(*client)
s.grpcCli = &typesmocks.Chain33Client{}
......@@ -103,6 +103,8 @@ func (s *suiteParaClient) initEnv(cfg *types.Config, sub *types.ConfigSubModule)
ret := &types.Reply{IsOk: true, Msg: data}
s.grpcCli.On("QueryChain", mock.Anything, mock.Anything).Return(ret, nil).Maybe()
s.grpcCli.On("SendTransaction", mock.Anything, mock.Anything).Return(reply, nil).Maybe()
s.grpcCli.On("GetLastHeader", mock.Anything, mock.Anything).Return(&types.Header{Height: cfg.Consensus.StartHeight + minBlockNum}, nil).Maybe()
s.grpcCli.On("GetBlockHash", mock.Anything, mock.Anything).Return(&types.ReplyHash{Hash: []byte("1")}, nil).Maybe()
s.para.grpcClient = s.grpcCli
s.para.SetQueueClient(q.Client())
......
......@@ -49,5 +49,4 @@ cli send jsvm call -a "{\"hello\": \"world\"}" -f hello -n test -k 14KEKbYtKKQm
第四步:query test合约hello函数
cli jsvm query -a "{\"hello\": \"world\"}" -f hello -n test
*/
......@@ -27,3 +27,18 @@ func (action *Action) GetMainHeightByTxHash(txHash []byte) int64 {
return -1
}
// GetMainBlockHashByHeight get Hash
func (action *Action) GetMainBlockHashByHeight(height int64) ([]byte, error) {
for i := 0; i < retryNum; i++ {
req := &types.ReqInt{Height: height}
replyHash, err := action.grpcClient.GetBlockHash(context.Background(), req)
if err != nil {
time.Sleep(time.Second)
} else {
return replyHash.Hash, nil
}
}
return nil, types.ErrBlockNotFound
}
......@@ -127,6 +127,7 @@ type Action struct {
conn *grpc.ClientConn
grpcClient types.Chain33Client
index int
lottery *Lottery
}
// NewLotteryAction generate New Action
......@@ -135,10 +136,9 @@ func NewLotteryAction(l *Lottery, tx *types.Transaction, index int) *Action {
fromaddr := tx.From()
msgRecvOp := grpc.WithMaxMsgSize(grpcRecSize)
if types.IsPara() && cfg.ParaRemoteGrpcClient == "" {
panic("ParaRemoteGrpcClient error")
}
conn, err := grpc.Dial(cfg.ParaRemoteGrpcClient, grpc.WithInsecure(), msgRecvOp)
paraRemoteGrpcClient := types.Conf("config.consensus").GStr("ParaRemoteGrpcClient")
conn, err := grpc.Dial(paraRemoteGrpcClient, grpc.WithInsecure(), msgRecvOp)
if err != nil {
panic(err)
......@@ -146,7 +146,7 @@ func NewLotteryAction(l *Lottery, tx *types.Transaction, index int) *Action {
grpcClient := types.NewChain33Client(conn)
return &Action{l.GetCoinsAccount(), l.GetStateDB(), hash, fromaddr, l.GetBlockTime(),
l.GetHeight(), dapp.ExecAddress(string(tx.Execer)), l.GetDifficulty(), l.GetAPI(), conn, grpcClient, index}
l.GetHeight(), dapp.ExecAddress(string(tx.Execer)), l.GetDifficulty(), l.GetAPI(), conn, grpcClient, index, l}
}
// GetLottCommonRecipt generate logs for lottery common action
......@@ -569,7 +569,6 @@ func (action *Action) LotteryClose(draw *pty.LotteryClose) (*types.Receipt, erro
func (action *Action) findLuckyNum(isSolo bool, lott *LotteryDB) int64 {
var num int64
var msg types.Message
var err error
var hash []byte
if isSolo {
//used for internal verification
......@@ -579,7 +578,12 @@ func (action *Action) findLuckyNum(isSolo bool, lott *LotteryDB) int64 {
//在主链上,当前高度查询不到,如果要保证区块个数,高度传入action.height-1
llog.Debug("findLuckyNum on randnum module")
if !types.IsPara() {
req := &types.ReqRandHash{ExecName: "ticket", Height: action.height - 1, BlockNum: blockNum}
blockHash, err := action.api.GetBlockHash(&types.ReqInt{Height: action.height - 1})
if err != nil {
return -1
}
req := &types.ReqRandHash{ExecName: "ticket", Hash: blockHash.Hash, BlockNum: blockNum}
msg, err = action.api.Query("ticket", "RandNumHash", req)
if err != nil {
return -1
......@@ -587,12 +591,20 @@ func (action *Action) findLuckyNum(isSolo bool, lott *LotteryDB) int64 {
reply := msg.(*types.ReplyHash)
hash = reply.Hash
} else {
mainHeight := action.GetMainHeightByTxHash(action.txhash)
if mainHeight < 0 {
llog.Error("findLuckyNum", "mainHeight", mainHeight)
txs := action.lottery.GetTxs()
if len(txs) < action.index+1 {
llog.Error("findLuckyNum", "len(txs)", len(txs), "index", action.index)
return -1
}
req := &types.ReqRandHash{ExecName: "ticket", Height: mainHeight, BlockNum: blockNum}
msg, err := action.api.Query("paracross", "GetMainBlockHash", txs[0])
if err != nil {
return -1
}
queryReply := msg.(*types.ReplyHash)
mainBlockHash := queryReply.Hash
req := &types.ReqRandHash{ExecName: "ticket", Hash: mainBlockHash, BlockNum: blockNum}
reply, err := action.grpcClient.QueryRandNum(context.Background(), req)
if err != nil {
return -1
......
......@@ -12,6 +12,7 @@ import (
"strings"
"github.com/33cn/chain33/rpc/jsonclient"
"github.com/33cn/chain33/system/dapp/commands"
"github.com/33cn/chain33/types"
pt "github.com/33cn/plugin/plugin/dapp/paracross/types"
"github.com/spf13/cobra"
......@@ -162,19 +163,12 @@ func addCreateTransferFlags(cmd *cobra.Command) {
cmd.Flags().StringP("note", "n", "", "transaction note info")
cmd.Flags().StringP("title", "", "", "the title of para chain, like `p.user.guodun.`")
cmd.MarkFlagRequired("title")
cmd.Flags().StringP("symbol", "s", "", "default for bty, symbol for token")
cmd.MarkFlagRequired("symbol")
}
func createTransfer(cmd *cobra.Command, args []string) {
txHex, err := createTransferTx(cmd, false)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
fmt.Println(txHex)
commands.CreateAssetTransfer(cmd, args, pt.ParaX)
}
//CreateRawTransferToExecCmd create raw transfer to exec tx
......@@ -189,27 +183,20 @@ func CreateRawTransferToExecCmd() *cobra.Command {
}
func addCreateTransferToExecFlags(cmd *cobra.Command) {
cmd.Flags().StringP("to", "t", "", "receiver exec name")
cmd.MarkFlagRequired("to")
cmd.Flags().Float64P("amount", "a", 0, "transaction amount")
cmd.MarkFlagRequired("amount")
cmd.Flags().StringP("note", "n", "", "transaction note info")
cmd.Flags().StringP("title", "", "", "the title of para chain, like `p.user.guodun.`")
cmd.MarkFlagRequired("title")
cmd.Flags().StringP("symbol", "s", "coins.bty", "default for bty, symbol for token")
cmd.MarkFlagRequired("symbol")
cmd.Flags().StringP("symbol", "s", "", "default for bty, symbol for token")
cmd.Flags().StringP("exec", "e", "", "asset deposit exec")
cmd.MarkFlagRequired("exec")
}
func createTransferToExec(cmd *cobra.Command, args []string) {
txHex, err := createTransferTx(cmd, false)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
fmt.Println(txHex)
commands.CreateAssetSendToExec(cmd, args, pt.ParaX)
}
//CreateRawWithdrawCmd create raw withdraw tx
......@@ -229,59 +216,15 @@ func addCreateWithdrawFlags(cmd *cobra.Command) {
cmd.Flags().StringP("note", "n", "", "transaction note info")
cmd.Flags().StringP("title", "", "", "the title of para chain, like `p.user.guodun.`")
cmd.MarkFlagRequired("title")
cmd.Flags().StringP("from", "t", "", "exec name")
cmd.MarkFlagRequired("from")
cmd.Flags().StringP("symbol", "s", "", "default for bty, symbol for token")
}
cmd.MarkFlagRequired("symbol")
func createWithdraw(cmd *cobra.Command, args []string) {
txHex, err := createTransferTx(cmd, true)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
fmt.Println(txHex)
cmd.Flags().StringP("exec", "e", "", "asset deposit exec")
cmd.MarkFlagRequired("exec")
}
func createTransferTx(cmd *cobra.Command, isWithdraw bool) (string, error) {
amount, _ := cmd.Flags().GetFloat64("amount")
if amount < 0 {
return "", types.ErrAmount
}
amountInt64 := int64(math.Trunc((amount+0.0000001)*1e4)) * 1e4
toAddr, _ := cmd.Flags().GetString("to")
note, _ := cmd.Flags().GetString("note")
symbol, _ := cmd.Flags().GetString("symbol")
title, _ := cmd.Flags().GetString("title")
if !strings.HasPrefix(title, "user.p") {
fmt.Fprintln(os.Stderr, "title is not right, title format like `user.p.guodun.`")
return "", types.ErrInvalidParam
}
execName := title + pt.ParaX
param := types.CreateTx{
To: toAddr,
Amount: amountInt64,
Fee: 0,
Note: []byte(note),
IsWithdraw: isWithdraw,
IsToken: false,
TokenSymbol: symbol,
ExecName: execName,
}
tx, err := pt.CreateRawTransferTx(&param)
if err != nil {
return "", err
}
txHex := types.Encode(tx)
return hex.EncodeToString(txHex), nil
func createWithdraw(cmd *cobra.Command, args []string) {
commands.CreateAssetWithdraw(cmd, args, pt.ParaX)
}
// IsSyncCmd query parachain is sync
......
......@@ -40,6 +40,38 @@ func (p *Paracross) Query_GetAssetTxResult(in *types.ReqHash) (types.Message, er
return p.paracrossGetAssetTxResult(in.Hash)
}
// Query_GetMainBlockHash query get mainblockHash by tx
func (p *Paracross) Query_GetMainBlockHash(in *types.Transaction) (types.Message, error) {
if in == nil {
return nil, types.ErrInvalidParam
}
return p.paracrossGetMainBlockHash(in)
}
func (p *Paracross) paracrossGetMainBlockHash(tx *types.Transaction) (types.Message, error) {
var paraAction pt.ParacrossAction
err := types.Decode(tx.GetPayload(), &paraAction)
if err != nil {
return nil, err
}
if paraAction.GetTy() != pt.ParacrossActionMiner {
return nil, types.ErrCoinBaseTxType
}
if paraAction.GetMiner() == nil {
return nil, pt.ErrParaEmptyMinerTx
}
paraNodeStatus := paraAction.GetMiner().GetStatus()
if paraNodeStatus == nil {
return nil, types.ErrCoinBaseTxType
}
mainHashFromNode := paraNodeStatus.MainBlockHash
return &types.ReplyHash{Hash: mainHashFromNode}, nil
}
func (p *Paracross) paracrossGetHeight(title string) (types.Message, error) {
ret, err := getTitle(p.GetStateDB(), calcTitleKey(title))
if err != nil {
......
......@@ -5,7 +5,8 @@
package types
import (
fmt "fmt"
"encoding/json"
"fmt"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/common/log/log15"
......@@ -187,34 +188,28 @@ func CreateRawMinerTx(status *ParacrossNodeStatus) (*types.Transaction, error) {
}
// CreateRawTransferTx create paracross asset transfer tx with transfer and withdraw
func CreateRawTransferTx(param *types.CreateTx) (*types.Transaction, error) {
if !types.IsParaExecName(param.GetExecName()) {
tlog.Error("CreateRawTransferTx", "exec", param.GetExecName())
return nil, types.ErrInvalidParam
}
transfer := &ParacrossAction{}
if !param.IsWithdraw {
v := &ParacrossAction_Transfer{Transfer: &types.AssetsTransfer{
Amount: param.Amount, Note: param.GetNote(), To: param.GetTo(), Cointoken: param.TokenSymbol}}
transfer.Value = v
transfer.Ty = ParacrossActionTransfer
} else {
v := &ParacrossAction_Withdraw{Withdraw: &types.AssetsWithdraw{
Amount: param.Amount, Note: param.GetNote(), To: param.GetTo(), Cointoken: param.TokenSymbol}}
transfer.Value = v
transfer.Ty = ParacrossActionWithdraw
}
tx := &types.Transaction{
Execer: []byte(param.GetExecName()),
Payload: types.Encode(transfer),
To: address.ExecAddress(param.GetExecName()),
Fee: param.Fee,
}
var err error
tx, err = types.FormatTx(param.GetExecName(), tx)
func (p ParacrossType) CreateRawTransferTx(action string, param json.RawMessage) (*types.Transaction, error) {
tlog.Error("ParacrossType CreateTx failed", "action", action, "msg", string(param))
tx, err := p.ExecTypeBase.CreateTx(action, param)
if err != nil {
tlog.Error("ParacrossType CreateTx failed", "err", err, "action", action, "msg", string(param))
return nil, err
}
if !types.IsPara() {
var transfer ParacrossAction
err = types.Decode(tx.Payload, &transfer)
if err != nil {
tlog.Error("ParacrossType CreateTx failed", "decode payload err", err, "action", action, "msg", string(param))
return nil, err
}
if action == "Transfer" {
tx.To = transfer.GetTransfer().To
} else if action == "Withdraw" {
tx.To = transfer.GetWithdraw().To
} else if action == "TransferToExec" {
tx.To = transfer.GetTransferToExec().To
}
}
return tx, nil
}
......@@ -98,15 +98,16 @@ func (p ParacrossType) CreateTx(action string, message json.RawMessage) (*types.
}
return CreateRawAssetTransferTx(&param)
} else if action == "ParacrossTransfer" || action == "ParacrossWithdraw" || action == "ParacrossTransferToExec" {
} else if action == "ParacrossTransfer" || action == "Transfer" ||
action == "ParacrossWithdraw" || action == "Withdraw" ||
action == "ParacrossTransferToExec" || action == "TransferToExec" {
var param types.CreateTx
err := json.Unmarshal(message, &param)
if err != nil {
glog.Error("CreateTx", "Error", err)
return nil, types.ErrInvalidParam
}
return CreateRawTransferTx(&param)
return p.CreateRawTransferTx(action, message)
}
return nil, types.ErrNotSupport
......
......@@ -28,6 +28,7 @@ func PokerBullCmd() *cobra.Command {
PokerBullContinueRawTxCmd(),
PokerBullQuitRawTxCmd(),
PokerBullQueryResultRawTxCmd(),
PokerBullPlayRawTxCmd(),
)
return cmd
......@@ -45,7 +46,7 @@ func PokerBullStartRawTxCmd() *cobra.Command {
}
func addPokerbullStartFlags(cmd *cobra.Command) {
cmd.Flags().Uint64P("value", "a", 0, "value")
cmd.Flags().Uint64P("value", "v", 0, "value")
cmd.MarkFlagRequired("value")
cmd.Flags().Uint32P("playerCount", "p", 0, "player count")
......@@ -121,7 +122,7 @@ func pokerbullQuit(cmd *cobra.Command, args []string) {
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(pkt.PokerBullX),
ActionName: pkt.CreatequitTx,
ActionName: pkt.CreateQuitTx,
Payload: []byte(fmt.Sprintf("{\"gameId\":\"%s\"}", gameID)),
}
......@@ -130,6 +131,54 @@ func pokerbullQuit(cmd *cobra.Command, args []string) {
ctx.RunWithoutMarshal()
}
// PokerBullPlayRawTxCmd 生成已匹配玩家游戏命令行
func PokerBullPlayRawTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "play",
Short: "Play game",
Run: pokerbullPlay,
}
addPokerbullPlayFlags(cmd)
return cmd
}
func addPokerbullPlayFlags(cmd *cobra.Command) {
cmd.Flags().StringP("gameID", "g", "", "game ID")
cmd.MarkFlagRequired("gameID")
cmd.Flags().Uint32P("round", "r", 0, "round")
cmd.MarkFlagRequired("round")
cmd.Flags().Uint64P("value", "v", 0, "value")
cmd.MarkFlagRequired("value")
cmd.Flags().StringArrayP("address", "a", nil, "address")
cmd.MarkFlagRequired("address")
}
func pokerbullPlay(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
gameID, _ := cmd.Flags().GetString("gameID")
round, _ := cmd.Flags().GetUint32("round")
value, _ := cmd.Flags().GetUint64("value")
address, _ := cmd.Flags().GetStringArray("address")
payload := &pkt.PBGamePlay{
GameId: gameID,
Value: int64(value) * types.Coin,
Round: int32(round),
}
payload.Address = make([]string, len(address))
copy(payload.Address, address)
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(pkt.PokerBullX),
ActionName: pkt.CreatePlayTx,
Payload: types.MustPBToJSON(payload),
}
var res string
ctx := jsonrpc.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, &res)
ctx.RunWithoutMarshal()
}
// PokerBullQueryResultRawTxCmd 查询命令行
func PokerBullQueryResultRawTxCmd() *cobra.Command {
cmd := &cobra.Command{
......
......@@ -26,3 +26,9 @@ func (c *PokerBull) Exec_Quit(payload *pkt.PBGameQuit, tx *types.Transaction, in
action := NewAction(c, tx, index)
return action.GameQuit(payload)
}
// Exec_Play 已匹配玩家直接开始游戏
func (c *PokerBull) Exec_Play(payload *pkt.PBGamePlay, tx *types.Transaction, index int) (*types.Receipt, error) {
action := NewAction(c, tx, index)
return action.GamePlay(payload)
}
......@@ -57,7 +57,7 @@ func (c *PokerBull) execLocal(receipt *types.ReceiptData) (*types.LocalDBSet, er
dbSet := &types.LocalDBSet{}
for i := 0; i < len(receipt.Logs); i++ {
item := receipt.Logs[i]
if item.Ty == pkt.TyLogPBGameStart || item.Ty == pkt.TyLogPBGameContinue || item.Ty == pkt.TyLogPBGameQuit {
if item.Ty == pkt.TyLogPBGameStart || item.Ty == pkt.TyLogPBGameContinue || item.Ty == pkt.TyLogPBGameQuit || item.Ty == pkt.TyLogPBGamePlay {
var Gamelog pkt.ReceiptPBGame
err := types.Decode(item.Log, &Gamelog)
if err != nil {
......@@ -84,3 +84,8 @@ func (c *PokerBull) ExecLocal_Continue(payload *pkt.PBGameContinue, tx *types.Tr
func (c *PokerBull) ExecLocal_Quit(payload *pkt.PBGameQuit, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return c.execLocal(receiptData)
}
// ExecLocal_Play 已匹配游戏交易local执行
func (c *PokerBull) ExecLocal_Play(payload *pkt.PBGamePlay, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return c.execLocal(receiptData)
}
......@@ -5,11 +5,13 @@
package executor
import (
"errors"
"fmt"
"sort"
"strconv"
"strings"
"time"
"github.com/33cn/chain33/account"
"github.com/33cn/chain33/common"
dbm "github.com/33cn/chain33/common/db"
......@@ -183,6 +185,8 @@ func (action *Action) GetReceiptLog(game *pkt.PokerBull) *types.ReceiptLog {
log.Ty = pkt.TyLogPBGameContinue
} else if game.Status == pkt.PBGameActionQuit {
log.Ty = pkt.TyLogPBGameQuit
} else if game.Status == pkt.PBGameActionPlay {
log.Ty = pkt.TyLogPBGamePlay
}
r.GameId = game.GameId
......@@ -327,11 +331,11 @@ func (action *Action) settleDealerAccount(lastAddress string, game *pkt.PokerBul
result := action.calculateDealer(game)
for _, hand := range result.Hands {
// 最后一名玩家没有冻结
if hand.Address != lastAddress {
if lastAddress != "" && hand.Address != lastAddress {
receipt, err := action.coinsAccount.ExecActive(hand.Address, action.execaddr, game.GetValue()*PokerbullLeverageMax)
if err != nil {
logger.Error("GameSettleDealer.ExecActive", "addr", hand.Address, "execaddr", action.execaddr, "amount", game.GetValue(),
"err", err)
logger.Error("GameSettleDealer.ExecActive", "GameID", game.GetGameId(), "addr", hand.Address,
"execaddr", action.execaddr, "amount", game.GetValue(), "err", err)
return nil, nil, err
}
logs = append(logs, receipt.Logs...)
......@@ -346,16 +350,16 @@ func (action *Action) settleDealerAccount(lastAddress string, game *pkt.PokerBul
receipt, err = action.coinsAccount.ExecTransfer(result.Dealer, hand.Address, action.execaddr, game.GetValue()*int64(hand.Leverage))
if err != nil {
action.coinsAccount.ExecFrozen(hand.Address, action.execaddr, game.GetValue()) // rollback
logger.Error("GameSettleDealer.ExecTransfer", "addr", hand.Address, "execaddr", action.execaddr,
"amount", game.GetValue()*int64(hand.Leverage), "err", err)
logger.Error("GameSettleDealer.ExecTransfer", "GameID", game.GetGameId(), "addr", hand.Address,
"execaddr", action.execaddr, "amount", game.GetValue()*int64(hand.Leverage), "err", err)
return nil, nil, err
}
} else {
receipt, err = action.coinsAccount.ExecTransfer(hand.Address, result.Dealer, action.execaddr, game.GetValue()*int64(result.DealerLeverage))
if err != nil {
action.coinsAccount.ExecFrozen(hand.Address, action.execaddr, game.GetValue()) // rollback
logger.Error("GameSettleDealer.ExecTransfer", "addr", hand.Address, "execaddr", action.execaddr,
"amount", game.GetValue()*int64(result.DealerLeverage), "err", err)
logger.Error("GameSettleDealer.ExecTransfer", "GameID", game.GetGameId(), "addr", hand.Address,
"execaddr", action.execaddr, "amount", game.GetValue()*int64(result.DealerLeverage), "err", err)
return nil, nil, err
}
}
......@@ -375,11 +379,11 @@ func (action *Action) settleDefaultAccount(lastAddress string, game *pkt.PokerBu
for _, player := range game.Players {
// 最后一名玩家没有冻结
if player.Address != lastAddress {
if lastAddress != "" && player.Address != lastAddress {
receipt, err := action.coinsAccount.ExecActive(player.GetAddress(), action.execaddr, game.GetValue()*PokerbullLeverageMax)
if err != nil {
logger.Error("GameSettleDefault.ExecActive", "addr", player.GetAddress(), "execaddr", action.execaddr,
"amount", game.GetValue()*PokerbullLeverageMax, "err", err)
logger.Error("GameSettleDefault.ExecActive", "GameID", game.GetGameId(), "addr", player.GetAddress(),
"execaddr", action.execaddr, "amount", game.GetValue()*PokerbullLeverageMax, "err", err)
return nil, nil, err
}
logs = append(logs, receipt.Logs...)
......@@ -391,8 +395,8 @@ func (action *Action) settleDefaultAccount(lastAddress string, game *pkt.PokerBu
receipt, err := action.coinsAccount.ExecTransfer(player.Address, result.Winner, action.execaddr, game.GetValue() /**int64(result.Leverage)*/) //TODO Dealer:暂时不支持倍数
if err != nil {
action.coinsAccount.ExecFrozen(result.Winner, action.execaddr, game.GetValue()) // rollback
logger.Error("GameSettleDefault.ExecTransfer", "addr", result.Winner, "execaddr", action.execaddr,
"amount", game.GetValue() /**int64(result.Leverage)*/, "err", err) //TODO Dealer:暂时不支持倍数
logger.Error("GameSettleDefault.ExecTransfer", "GameID", game.GetGameId(), "addr", result.Winner,
"execaddr", action.execaddr, "amount", game.GetValue() /**int64(result.Leverage)*/, "err", err) //TODO Dealer:暂时不支持倍数
return nil, nil, err
}
logs = append(logs, receipt.Logs...)
......@@ -438,8 +442,8 @@ func (action *Action) settleAccount(lastAddress string, game *pkt.PokerBull) ([]
}
func (action *Action) genTxRnd(txhash []byte) (int64, error) {
randbyte := make([]byte, 7)
for i := 0; i < 7; i++ {
randbyte := make([]byte, 6)
for i := 0; i < 6; i++ {
randbyte[i] = txhash[i]
}
......@@ -452,15 +456,35 @@ func (action *Action) genTxRnd(txhash []byte) (int64, error) {
return randint, nil
}
func (action *Action) checkDupPlayerAddress(id string, pbPlayers []*pkt.PBPlayer) error {
func (action *Action) genTxRnds(txhash []byte, playnum int32) ([]int64, error) {
rands := make([]int64, playnum)
for i := 0; i < int(playnum); i++ {
randbyte := make([]byte, 6)
for j := 0; j < 6; j++ {
randbyte[j] = txhash[i*6+j]
}
randstr := common.ToHex(randbyte)
randint, err := strconv.ParseInt(randstr, 0, 64)
if err != nil {
return nil, err
}
rands[i] = randint
}
return rands, nil
}
func (action *Action) checkPlayerAddressExist(pbPlayers []*pkt.PBPlayer) bool {
for _, player := range pbPlayers {
if action.fromaddr == player.Address {
logger.Error("Poker bull game start", "addr", action.fromaddr, "execaddr", action.execaddr, "Already in a game", id)
return errors.New("Address is already in a game")
return true
}
}
return nil
return false
}
// 新建一局游戏
......@@ -475,8 +499,7 @@ func (action *Action) newGame(gameID string, start *pkt.PBGameStart) (*pkt.Poker
//TODO 庄家检查闲家数量倍数的资金
if pkt.DefaultStyle == pkt.PlayStyleDealer {
if !action.CheckExecAccountBalance(action.fromaddr, start.GetValue()*PokerbullLeverageMax*int64(start.PlayerNum-1), 0) {
logger.Error("GameStart", "addr", action.fromaddr, "execaddr", action.execaddr, "id",
gameID, "err", types.ErrNoBalance)
logger.Error("GameStart", "GameID", gameID, "addr", action.fromaddr, "execaddr", action.execaddr, "err", types.ErrNoBalance)
return nil, types.ErrNoBalance
}
}
......@@ -484,7 +507,7 @@ func (action *Action) newGame(gameID string, start *pkt.PBGameStart) (*pkt.Poker
game = &pkt.PokerBull{
GameId: gameID,
Status: pkt.PBGameActionStart,
StartTime: action.blocktime,
StartTime: time.Unix(action.blocktime, 0).Format("2006-01-02 15:04:05"),
StartTxHash: gameID,
Value: start.GetValue(),
Poker: NewPoker(),
......@@ -497,7 +520,7 @@ func (action *Action) newGame(gameID string, start *pkt.PBGameStart) (*pkt.Poker
}
Shuffle(game.Poker, action.blocktime) //洗牌
logger.Debug(fmt.Sprintf("Start a new game %s for player %s", game.GameId, action.fromaddr))
logger.Info(fmt.Sprintf("Create a new game %s for player %s", game.GameId, action.fromaddr))
return game, nil
}
......@@ -505,27 +528,37 @@ func (action *Action) newGame(gameID string, start *pkt.PBGameStart) (*pkt.Poker
// 筛选合适的牌局
func (action *Action) selectGameFromIds(ids []string, value int64) *pkt.PokerBull {
var gameRet *pkt.PokerBull
for _, id := range ids {
for num := len(ids) - 1; num > -1; num-- {
id := ids[num]
game, err := action.readGame(id)
if err != nil {
logger.Error("Poker bull game start", "addr", action.fromaddr, "execaddr", action.execaddr, "get game failed", id, "err", err)
logger.Error("Poker bull game start", "GameID", id, "addr", action.fromaddr, "execaddr", action.execaddr,
"get game failed", "err", err)
continue
}
// 玩家已经满了,不需要再匹配(防止多交易在同一区块没有刷新localdb的场景)
if int32(len(game.Players)) == game.PlayerNum {
continue
}
//不能自己和自己玩
if action.checkDupPlayerAddress(id, game.Players) != nil {
if action.checkPlayerAddressExist(game.Players) {
logger.Info(fmt.Sprintf("Player %s already exist in game %s", action.fromaddr, id))
continue
}
//选择合适赌注的游戏
if value == 0 && game.GetValue() != pkt.MinPlayValue {
if !action.CheckExecAccountBalance(action.fromaddr, game.GetValue(), 0) {
logger.Error("GameStart", "addr", action.fromaddr, "execaddr", action.execaddr, "id", id, "err", types.ErrNoBalance)
logger.Error("GameStart", "GameID", id, "addr", action.fromaddr, "execaddr", action.execaddr,
"err", types.ErrNoBalance)
continue
}
}
gameRet = game
logger.Info(fmt.Sprintf("Match a new game %s for player %s", id, action.fromaddr))
break
}
return gameRet
......@@ -554,7 +587,7 @@ func (action *Action) GameStart(start *pkt.PBGameStart) (*types.Receipt, error)
var logs []*types.ReceiptLog
var kv []*types.KeyValue
logger.Debug(fmt.Sprintf("Pokerbull game start for %s", action.fromaddr))
logger.Info(fmt.Sprintf("Pokerbull game match for %s", action.fromaddr))
if start.PlayerNum > pkt.MaxPlayerNum {
logger.Error("GameStart", "addr", action.fromaddr, "execaddr", action.execaddr,
"err", fmt.Sprintf("The maximum player number is %d", pkt.MaxPlayerNum))
......@@ -563,7 +596,7 @@ func (action *Action) GameStart(start *pkt.PBGameStart) (*types.Receipt, error)
gameID := common.ToHex(action.txhash)
if !action.CheckExecAccountBalance(action.fromaddr, start.GetValue()*PokerbullLeverageMax, 0) {
logger.Error("GameStart", "addr", action.fromaddr, "execaddr", action.execaddr, "id", gameID, "err", types.ErrNoBalance)
logger.Error("GameStart", "GameID", gameID, "addr", action.fromaddr, "execaddr", action.execaddr, "err", types.ErrNoBalance)
return nil, types.ErrNoBalance
}
......@@ -593,7 +626,6 @@ func (action *Action) GameStart(start *pkt.PBGameStart) (*types.Receipt, error)
return nil, err
}
}
logger.Debug(fmt.Sprintf("Match a new game %s for player %s", game.GameId, game.GameId))
}
//发牌随机数取txhash
......@@ -604,14 +636,15 @@ func (action *Action) GameStart(start *pkt.PBGameStart) (*types.Receipt, error)
//加入当前玩家信息
game.Players = append(game.Players, &pkt.PBPlayer{
Address: action.fromaddr,
TxHash: txrng,
Ready: false,
Address: action.fromaddr,
TxHash: txrng,
Ready: false,
MatchTime: time.Unix(action.blocktime, 0).Format("2006-01-02 15:04:05"),
})
// 如果人数达标,则发牌计算斗牛结果
if len(game.Players) == int(game.PlayerNum) {
logger.Debug(fmt.Sprintf("Game start: %s", game.GameId))
logger.Info(fmt.Sprintf("Game starting: %s round: %d", game.GameId, game.Round))
logsH, kvH, err := action.settleAccount(action.fromaddr, game)
if err != nil {
return nil, err
......@@ -625,10 +658,11 @@ func (action *Action) GameStart(start *pkt.PBGameStart) (*types.Receipt, error)
game.PreStatus = pkt.PBGameActionStart
game.IsWaiting = false
} else {
logger.Debug(fmt.Sprintf("Game waiting: %s", game.GameId))
logger.Info(fmt.Sprintf("Game waiting: %s round: %d", game.GameId, game.Round))
receipt, err := action.coinsAccount.ExecFrozen(action.fromaddr, action.execaddr, start.GetValue()*PokerbullLeverageMax) //冻结子账户资金, 最后一位玩家不需要冻结
if err != nil {
logger.Error("GameCreate.ExecFrozen", "addr", action.fromaddr, "execaddr", action.execaddr, "amount", start.GetValue(), "err", err.Error())
logger.Error("GameCreate.ExecFrozen", "GameID", gameID, "addr", action.fromaddr, "execaddr", action.execaddr,
"amount", start.GetValue(), "err", err.Error())
return nil, err
}
logs = append(logs, receipt.Logs...)
......@@ -667,17 +701,17 @@ func (action *Action) GameContinue(pbcontinue *pkt.PBGameContinue) (*types.Recei
game, err := action.readGame(pbcontinue.GetGameId())
if err != nil {
logger.Error("GameContinue", "addr", action.fromaddr, "execaddr", action.execaddr, "get game failed, gameID",
pbcontinue.GetGameId(), "err", err)
logger.Error("GameContinue", "GameID", pbcontinue.GetGameId(), "addr", action.fromaddr, "execaddr",
action.execaddr, "get game failed", "err", err)
return nil, err
}
if game.Status != pkt.PBGameActionContinue {
logger.Error("GameContinue", "addr", action.fromaddr, "execaddr", action.execaddr, "Status error, gameID",
pbcontinue.GetGameId())
logger.Error("GameContinue", "GameID", pbcontinue.GetGameId(), "addr", action.fromaddr, "execaddr",
action.execaddr, "Status error")
return nil, err
}
logger.Debug(fmt.Sprintf("Pokerbull game %s continue for %s", game.GameId, action.fromaddr))
logger.Info(fmt.Sprintf("Continue pokerbull game %s from %s", game.GameId, action.fromaddr))
// 检查余额,庄家检查闲家数量倍数的资金
checkValue := game.GetValue() * PokerbullLeverageMax
......@@ -685,21 +719,21 @@ func (action *Action) GameContinue(pbcontinue *pkt.PBGameContinue) (*types.Recei
checkValue = checkValue * int64(game.PlayerNum-1)
}
if !action.CheckExecAccountBalance(action.fromaddr, checkValue, 0) {
logger.Error("GameContinue", "addr", action.fromaddr, "execaddr", action.execaddr, "id",
pbcontinue.GetGameId(), "err", types.ErrNoBalance)
logger.Error("GameContinue", "GameID", pbcontinue.GetGameId(), "addr", action.fromaddr, "execaddr",
action.execaddr, "err", types.ErrNoBalance)
return nil, types.ErrNoBalance
}
// 寻找对应玩家
pbplayer := getPlayerFromAddress(game.Players, action.fromaddr)
if pbplayer == nil {
logger.Error("GameContinue", "addr", action.fromaddr, "execaddr", action.execaddr, "get game player failed",
pbcontinue.GetGameId(), "err", types.ErrNotFound)
logger.Error("GameContinue", "GameID", pbcontinue.GetGameId(), "addr", action.fromaddr, "execaddr",
action.execaddr, "get game player failed", "err", types.ErrNotFound)
return nil, types.ErrNotFound
}
if pbplayer.Ready {
logger.Error("GameContinue", "addr", action.fromaddr, "execaddr", action.execaddr, "player has been ready",
pbcontinue.GetGameId(), "player", pbplayer.Address)
logger.Error("GameContinue", "GameID", pbcontinue.GetGameId(), "addr", action.fromaddr, "execaddr",
action.execaddr, "player has been ready")
return nil, fmt.Errorf("player %s has been ready", pbplayer.Address)
}
......@@ -710,9 +744,10 @@ func (action *Action) GameContinue(pbcontinue *pkt.PBGameContinue) (*types.Recei
}
pbplayer.TxHash = txrng
pbplayer.Ready = true
pbplayer.MatchTime = time.Unix(action.blocktime, 0).Format("2006-01-02 15:04:05")
if getReadyPlayerNum(game.Players) == int(game.PlayerNum) {
logger.Debug(fmt.Sprintf("Game start: %s", game.GameId))
logger.Info(fmt.Sprintf("Game starting: %s round: %d", game.GameId, game.Round))
logsH, kvH, err := action.settleAccount(action.fromaddr, game)
if err != nil {
return nil, err
......@@ -724,14 +759,15 @@ func (action *Action) GameContinue(pbcontinue *pkt.PBGameContinue) (*types.Recei
game.IsWaiting = false
game.PreStatus = pkt.PBGameActionContinue
} else {
logger.Debug(fmt.Sprintf("Game waiting: %s", game.GameId))
logger.Info(fmt.Sprintf("Game waiting: %s round: %d", game.GameId, game.Round))
// 回合数加一次
if !game.IsWaiting {
game.Round++
}
receipt, err := action.coinsAccount.ExecFrozen(action.fromaddr, action.execaddr, game.GetValue()*PokerbullLeverageMax) //冻结子账户资金,最后一位玩家不需要冻结
if err != nil {
logger.Error("GameCreate.ExecFrozen", "addr", action.fromaddr, "execaddr", action.execaddr, "amount", game.GetValue(), "err", err.Error())
logger.Error("GameCreate.ExecFrozen", "GameID", pbcontinue.GetGameId(), "addr", action.fromaddr,
"execaddr", action.execaddr, "amount", game.GetValue(), "err", err.Error())
return nil, err
}
logs = append(logs, receipt.Logs...)
......@@ -751,21 +787,35 @@ func (action *Action) GameQuit(pbend *pkt.PBGameQuit) (*types.Receipt, error) {
var logs []*types.ReceiptLog
var kv []*types.KeyValue
logger.Info(fmt.Sprintf("Quit pokerbull game %s", pbend.GameId))
game, err := action.readGame(pbend.GetGameId())
if err != nil {
logger.Error("GameEnd", "addr", action.fromaddr, "execaddr", action.execaddr, "get game failed",
pbend.GetGameId(), "err", err)
logger.Error("GameEnd", "GameID", pbend.GetGameId(), "addr", action.fromaddr, "execaddr",
action.execaddr, "get game failed", "err", err)
return nil, err
}
if game.Status == pkt.PBGameActionQuit {
logger.Error("Quit pokerbull game", "GameID", pbend.GetGameId(), "value", game.Value, "err", "already game over")
return nil, fmt.Errorf("already game over")
}
if !action.checkPlayerAddressExist(game.Players) {
if action.fromaddr != pkt.PlatformSignAddress {
logger.Error("GameEnd", "GameID", pbend.GetGameId(), "addr", action.fromaddr, "execaddr",
action.execaddr, "err", "permission denied")
return nil, fmt.Errorf("permission denied")
}
}
// 如果游戏没有开始,激活冻结账户
if game.IsWaiting {
if game.Status == pkt.PBGameActionStart {
for _, player := range game.Players {
receipt, err := action.coinsAccount.ExecActive(player.Address, action.execaddr, game.GetValue()*PokerbullLeverageMax)
if err != nil {
logger.Error("GameSettleDealer.ExecActive", "addr", player.Address, "execaddr", action.execaddr, "amount", game.GetValue(),
"err", err)
logger.Error("GameSettleDealer.ExecActive", "GameID", pbend.GetGameId(), "addr", player.Address,
"execaddr", action.execaddr, "amount", game.GetValue(), "err", err)
continue
}
logs = append(logs, receipt.Logs...)
......@@ -779,8 +829,8 @@ func (action *Action) GameQuit(pbend *pkt.PBGameQuit) (*types.Receipt, error) {
receipt, err := action.coinsAccount.ExecActive(player.Address, action.execaddr, game.GetValue()*PokerbullLeverageMax)
if err != nil {
logger.Error("GameSettleDealer.ExecActive", "addr", player.Address, "execaddr", action.execaddr, "amount", game.GetValue(),
"err", err)
logger.Error("GameSettleDealer.ExecActive", "GameID", pbend.GetGameId(), "addr", player.Address,
"execaddr", action.execaddr, "amount", game.GetValue(), "err", err)
continue
}
logs = append(logs, receipt.Logs...)
......@@ -793,7 +843,7 @@ func (action *Action) GameQuit(pbend *pkt.PBGameQuit) (*types.Receipt, error) {
game.Status = pkt.PBGameActionQuit
game.PrevIndex = game.Index
game.Index = action.getIndex(game)
game.QuitTime = action.blocktime
game.QuitTime = time.Unix(action.blocktime, 0).Format("2006-01-02 15:04:05")
game.QuitTxHash = common.ToHex(action.txhash)
receiptLog := action.GetReceiptLog(game)
......@@ -802,6 +852,123 @@ func (action *Action) GameQuit(pbend *pkt.PBGameQuit) (*types.Receipt, error) {
return &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}, nil
}
// GamePlay 已匹配玩家直接游戏
func (action *Action) GamePlay(pbplay *pkt.PBGamePlay) (*types.Receipt, error) {
var logs []*types.ReceiptLog
var kv []*types.KeyValue
logger.Info(fmt.Sprintf("Play pokerbull game %s, player:%s", pbplay.GameId, strings.Join(pbplay.Address, ",")))
// 校验签名地址
if action.fromaddr != pkt.PlatformSignAddress {
logger.Error("Pokerbull game play", "GameID", pbplay.GetGameId(), "round", pbplay.Round, "value",
pbplay.Value, "players", strings.Join(pbplay.Address, ","), "err", "permission denied")
return nil, fmt.Errorf("game signing address not support")
}
// 检查玩家人数
if len(pbplay.Address) < pkt.MinPlayerNum || len(pbplay.Address) > pkt.MaxPlayerNum {
logger.Error("Pokerbull game play", "GameID", pbplay.GetGameId(), "round", pbplay.Round, "value",
pbplay.Value, "players", strings.Join(pbplay.Address, ","), "err", "invalid player number")
return nil, fmt.Errorf("Invalid player number")
}
// 检查玩家地址余额
for _, addr := range pbplay.Address {
if !action.CheckExecAccountBalance(addr, pbplay.GetValue()*PokerbullLeverageMax, 0) {
logger.Error("GamePlay", "addr", addr, "execaddr", action.execaddr, "id", pbplay.GetGameId(), "err", types.ErrNoBalance)
return nil, types.ErrNoBalance
}
}
// 游戏存在则校验游戏状态,不存在则创建游戏
game, _ := action.readGame(pbplay.GetGameId())
if game != nil {
if game.Status == pkt.PBGameActionQuit {
logger.Error("Pokerbull game play", "GameID", pbplay.GetGameId(), "round", pbplay.Round, "value",
pbplay.Value, "players", strings.Join(pbplay.Address, ","), "err", "already game over")
return nil, fmt.Errorf("already game over")
}
if game.Round+1 != pbplay.Round {
logger.Error("Pokerbull game play", "GameID", pbplay.GetGameId(), "round", pbplay.Round, "value",
pbplay.Value, "players", strings.Join(pbplay.Address, ","), "err", "game round error")
return nil, fmt.Errorf("game round error")
}
if game.Value != pbplay.Value {
logger.Error("Pokerbull game play", "GameID", pbplay.GetGameId(), "round", pbplay.Round, "value",
pbplay.Value, "players", strings.Join(pbplay.Address, ","), "err", "game value error")
return nil, fmt.Errorf("game value error")
}
// 获取发牌随机数
rands, err := action.genTxRnds(action.txhash, game.PlayerNum)
if err != nil {
logger.Error("Pokerbull game play", "GameID", pbplay.GetGameId(), "round", pbplay.Round, "value",
pbplay.Value, "players", strings.Join(pbplay.Address, ","), "err", err)
return nil, err
}
// 更新玩家信息
for i, player := range game.Players {
player.TxHash = rands[i]
player.MatchTime = time.Unix(action.blocktime, 0).Format("2006-01-02 15:04:05")
}
game.Round++
game.Status = pkt.PBGameActionContinue // 更新游戏状态
game.PreStatus = pkt.PBGameActionContinue
} else {
gameNew, err := action.newGame(pbplay.GameId, &pkt.PBGameStart{Value: pbplay.Value, PlayerNum: int32(len(pbplay.Address))})
if err != nil {
logger.Error("Pokerbull game play", "GameID", pbplay.GetGameId(), "round", pbplay.Round, "value",
pbplay.Value, "players", strings.Join(pbplay.Address, ","), "err", err)
return nil, err
}
game = gameNew
// 获取发牌随机数
rands, err := action.genTxRnds(action.txhash, game.PlayerNum)
if err != nil {
logger.Error("Pokerbull game play", "GameID", pbplay.GetGameId(), "round", pbplay.Round, "value",
pbplay.Value, "players", strings.Join(pbplay.Address, ","), "err", err)
return nil, err
}
// 创建玩家信息
for i, addr := range pbplay.Address {
player := &pkt.PBPlayer{
Address: addr,
TxHash: rands[i],
MatchTime: time.Unix(action.blocktime, 0).Format("2006-01-02 15:04:05"),
}
game.Players = append(game.Players, player)
}
game.Status = pkt.PBGameActionQuit // 更新游戏状态
game.PreStatus = pkt.PBGameActionStart
game.QuitTime = time.Unix(action.blocktime, 0).Format("2006-01-02 15:04:05")
game.QuitTxHash = common.ToHex(action.txhash)
}
logger.Info(fmt.Sprintf("Game starting: %s round: %d", game.GameId, game.Round))
logsH, kvH, err := action.settleAccount("", game)
if err != nil {
return nil, err
}
logs = append(logs, logsH...)
kv = append(kv, kvH...)
game.PrevIndex = game.Index
game.Index = action.getIndex(game)
game.IsWaiting = false
receiptLog := action.GetReceiptLog(game)
logs = append(logs, receiptLog)
kv = append(kv, action.saveGame(game)...)
return &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}, nil
}
// HandSlice 一手牌
type HandSlice []*pkt.PBHand
......
......@@ -6,7 +6,7 @@ package types;
message PokerBull {
string gameId = 1; //默认是由创建这局游戏的txHash作为gameId
int32 status = 2; // Start 1 -> Continue 2 -> Quit 3
int64 startTime = 3; //开始时间
string startTime = 3; //开始时间
string startTxHash = 4; //游戏启动交易hash
int64 value = 5; //赌注
PBPoker poker = 6; //扑克牌
......@@ -15,7 +15,7 @@ message PokerBull {
repeated PBResult results = 9; //游戏结果集
int64 index = 10; //索引
int64 prevIndex = 11; //上级索引
int64 quitTime = 12; //游戏结束时间
string quitTime = 12; //游戏结束时间
string quitTxHash = 13; //游戏结束交易hash
string dealerAddr = 14; //下局庄家地址
bool isWaiting = 15; //游戏是否处于等待状态
......@@ -25,19 +25,21 @@ message PokerBull {
//一把牌
message PBHand {
repeated int32 cards = 1; //一把牌,五张
int32 result = 2; //斗牛结果 (没牛:0, 牛1-9:1-9, 牛牛:10)
string address = 3; //玩家地址
bool isWin = 4; //是否赢庄家
int32 leverage = 5; //赌注倍数
repeated int32 cards = 1; //一把牌,五张
int32 result = 2; //斗牛结果 (没牛:0, 牛1-9:1-9, 牛牛:10)
string address = 3; //玩家地址
bool isWin = 4; //是否赢庄家
int32 leverage = 5; //赌注倍数
string roundTime = 6; //本回合开始时间
}
//玩家
message PBPlayer {
repeated PBHand hands = 1; //历史发牌和斗牛结果
string address = 2; //玩家地址
int64 txHash = 3; //发牌随机数因子txhash的整数格式
bool ready = 4; // continue状态下,是否ready
repeated PBHand hands = 1; //历史发牌和斗牛结果
string address = 2; //玩家地址
int64 txHash = 3; //发牌随机数因子txhash的整数格式
bool ready = 4; //continue状态下,是否ready
string matchTime = 5; //玩家匹配时间
}
//本局游戏结果
......@@ -58,10 +60,11 @@ message PBPoker {
//游戏状态
message PBGameAction {
oneof value {
PBGameStart start = 1;
PBGameStart start = 1;
PBGameContinue continue = 2;
PBGameQuit quit = 3;
PBGameQuery query = 4;
PBGameQuit quit = 3;
PBGameQuery query = 4;
PBGamePlay play = 5;
}
int32 ty = 10;
}
......@@ -87,6 +90,14 @@ message PBGameQuery {
string gameId = 1;
}
//已匹配玩家直接游戏
message PBGamePlay {
string gameId = 1; //游戏id
int32 round = 2; //当前游戏回合数
int64 value = 3; //当前游戏赌注
repeated string address = 4; //玩家地址
}
//根据状态和游戏人数查找
message QueryPBGameListByStatusAndPlayerNum {
int32 status = 1;
......
......@@ -97,7 +97,7 @@ func testQuitRawTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
payload := &pty.PBGameQuit{GameId: "123"}
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(pty.PokerBullX),
ActionName: pty.CreatequitTx,
ActionName: pty.CreateQuitTx,
Payload: types.MustPBToJSON(payload),
}
var res string
......
......@@ -12,6 +12,7 @@ const (
PBGameActionContinue
PBGameActionQuit
PBGameActionQuery
PBGameActionPlay
)
const (
......@@ -30,6 +31,8 @@ const (
TyLogPBGameQuit = 723
// TyLogPBGameQuery log for query PBgame
TyLogPBGameQuery = 724
// TyLogPBGamePlay log for play PBgame
TyLogPBGamePlay = 725
)
//包的名字可以通过配置文件来配置
......@@ -56,8 +59,10 @@ const (
CreateStartTx = "Start"
// CreateContinueTx 创建继续交易
CreateContinueTx = "Continue"
// CreatequitTx 创建退出交易
CreatequitTx = "Quit"
// CreateQuitTx 创建退出交易
CreateQuitTx = "Quit"
// CreatePlayTx 创建已匹配玩家交易
CreatePlayTx = "Play"
)
const (
......@@ -67,6 +72,8 @@ const (
DefaultCount = int32(20)
// MaxPlayerNum 最大玩家数
MaxPlayerNum = 5
// MinPlayerNum 最小玩家数
MinPlayerNum = 2
// MinPlayValue 最小赌注
MinPlayValue = 10 * types.Coin
// DefaultStyle 默认游戏类型
......@@ -80,5 +87,7 @@ const (
// DeveloperFee 开发者佣金
DeveloperFee = int64(0.005 * float64(types.Coin))
// WinnerReturn 赢家回报率
WinnerReturn = types.Coin - DeveloperFee
WinnerReturn = types.Coin - DeveloperFee - PlatformFee
// PlatformSignAddress 平台签名地址
PlatformSignAddress = "1Geb4ppNiAwMKKyrJgcis3JA57FkqsXvdR"
)
......@@ -25,7 +25,7 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type PokerBull struct {
GameId string `protobuf:"bytes,1,opt,name=gameId,proto3" json:"gameId,omitempty"`
Status int32 `protobuf:"varint,2,opt,name=status,proto3" json:"status,omitempty"`
StartTime int64 `protobuf:"varint,3,opt,name=startTime,proto3" json:"startTime,omitempty"`
StartTime string `protobuf:"bytes,3,opt,name=startTime,proto3" json:"startTime,omitempty"`
StartTxHash string `protobuf:"bytes,4,opt,name=startTxHash,proto3" json:"startTxHash,omitempty"`
Value int64 `protobuf:"varint,5,opt,name=value,proto3" json:"value,omitempty"`
Poker *PBPoker `protobuf:"bytes,6,opt,name=poker,proto3" json:"poker,omitempty"`
......@@ -34,7 +34,7 @@ type PokerBull struct {
Results []*PBResult `protobuf:"bytes,9,rep,name=results,proto3" json:"results,omitempty"`
Index int64 `protobuf:"varint,10,opt,name=index,proto3" json:"index,omitempty"`
PrevIndex int64 `protobuf:"varint,11,opt,name=prevIndex,proto3" json:"prevIndex,omitempty"`
QuitTime int64 `protobuf:"varint,12,opt,name=quitTime,proto3" json:"quitTime,omitempty"`
QuitTime string `protobuf:"bytes,12,opt,name=quitTime,proto3" json:"quitTime,omitempty"`
QuitTxHash string `protobuf:"bytes,13,opt,name=quitTxHash,proto3" json:"quitTxHash,omitempty"`
DealerAddr string `protobuf:"bytes,14,opt,name=dealerAddr,proto3" json:"dealerAddr,omitempty"`
IsWaiting bool `protobuf:"varint,15,opt,name=isWaiting,proto3" json:"isWaiting,omitempty"`
......@@ -84,11 +84,11 @@ func (m *PokerBull) GetStatus() int32 {
return 0
}
func (m *PokerBull) GetStartTime() int64 {
func (m *PokerBull) GetStartTime() string {
if m != nil {
return m.StartTime
}
return 0
return ""
}
func (m *PokerBull) GetStartTxHash() string {
......@@ -147,11 +147,11 @@ func (m *PokerBull) GetPrevIndex() int64 {
return 0
}
func (m *PokerBull) GetQuitTime() int64 {
func (m *PokerBull) GetQuitTime() string {
if m != nil {
return m.QuitTime
}
return 0
return ""
}
func (m *PokerBull) GetQuitTxHash() string {
......@@ -196,6 +196,7 @@ type PBHand struct {
Address string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
IsWin bool `protobuf:"varint,4,opt,name=isWin,proto3" json:"isWin,omitempty"`
Leverage int32 `protobuf:"varint,5,opt,name=leverage,proto3" json:"leverage,omitempty"`
RoundTime string `protobuf:"bytes,6,opt,name=roundTime,proto3" json:"roundTime,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
......@@ -261,12 +262,20 @@ func (m *PBHand) GetLeverage() int32 {
return 0
}
func (m *PBHand) GetRoundTime() string {
if m != nil {
return m.RoundTime
}
return ""
}
//玩家
type PBPlayer struct {
Hands []*PBHand `protobuf:"bytes,1,rep,name=hands,proto3" json:"hands,omitempty"`
Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"`
TxHash int64 `protobuf:"varint,3,opt,name=txHash,proto3" json:"txHash,omitempty"`
Ready bool `protobuf:"varint,4,opt,name=ready,proto3" json:"ready,omitempty"`
MatchTime string `protobuf:"bytes,5,opt,name=matchTime,proto3" json:"matchTime,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
......@@ -325,6 +334,13 @@ func (m *PBPlayer) GetReady() bool {
return false
}
func (m *PBPlayer) GetMatchTime() string {
if m != nil {
return m.MatchTime
}
return ""
}
//本局游戏结果
type PBResult struct {
Hands []*PBHand `protobuf:"bytes,1,rep,name=hands,proto3" json:"hands,omitempty"`
......@@ -452,6 +468,7 @@ type PBGameAction struct {
// *PBGameAction_Continue
// *PBGameAction_Quit
// *PBGameAction_Query
// *PBGameAction_Play
Value isPBGameAction_Value `protobuf_oneof:"value"`
Ty int32 `protobuf:"varint,10,opt,name=ty,proto3" json:"ty,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
......@@ -504,6 +521,10 @@ type PBGameAction_Query struct {
Query *PBGameQuery `protobuf:"bytes,4,opt,name=query,proto3,oneof"`
}
type PBGameAction_Play struct {
Play *PBGamePlay `protobuf:"bytes,5,opt,name=play,proto3,oneof"`
}
func (*PBGameAction_Start) isPBGameAction_Value() {}
func (*PBGameAction_Continue) isPBGameAction_Value() {}
......@@ -512,6 +533,8 @@ func (*PBGameAction_Quit) isPBGameAction_Value() {}
func (*PBGameAction_Query) isPBGameAction_Value() {}
func (*PBGameAction_Play) isPBGameAction_Value() {}
func (m *PBGameAction) GetValue() isPBGameAction_Value {
if m != nil {
return m.Value
......@@ -547,6 +570,13 @@ func (m *PBGameAction) GetQuery() *PBGameQuery {
return nil
}
func (m *PBGameAction) GetPlay() *PBGamePlay {
if x, ok := m.GetValue().(*PBGameAction_Play); ok {
return x.Play
}
return nil
}
func (m *PBGameAction) GetTy() int32 {
if m != nil {
return m.Ty
......@@ -561,6 +591,7 @@ func (*PBGameAction) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer)
(*PBGameAction_Continue)(nil),
(*PBGameAction_Quit)(nil),
(*PBGameAction_Query)(nil),
(*PBGameAction_Play)(nil),
}
}
......@@ -588,6 +619,11 @@ func _PBGameAction_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
if err := b.EncodeMessage(x.Query); err != nil {
return err
}
case *PBGameAction_Play:
b.EncodeVarint(5<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.Play); err != nil {
return err
}
case nil:
default:
return fmt.Errorf("PBGameAction.Value has unexpected type %T", x)
......@@ -630,6 +666,14 @@ func _PBGameAction_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.B
err := b.DecodeMessage(msg)
m.Value = &PBGameAction_Query{msg}
return true, err
case 5: // value.play
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(PBGamePlay)
err := b.DecodeMessage(msg)
m.Value = &PBGameAction_Play{msg}
return true, err
default:
return false, nil
}
......@@ -659,6 +703,11 @@ func _PBGameAction_OneofSizer(msg proto.Message) (n int) {
n += 1 // tag and wire
n += proto.SizeVarint(uint64(s))
n += s
case *PBGameAction_Play:
s := proto.Size(x.Play)
n += 1 // tag and wire
n += proto.SizeVarint(uint64(s))
n += s
case nil:
default:
panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
......@@ -834,6 +883,70 @@ func (m *PBGameQuery) GetGameId() string {
return ""
}
//已匹配玩家直接游戏
type PBGamePlay struct {
GameId string `protobuf:"bytes,1,opt,name=gameId,proto3" json:"gameId,omitempty"`
Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"`
Value int64 `protobuf:"varint,3,opt,name=value,proto3" json:"value,omitempty"`
Address []string `protobuf:"bytes,4,rep,name=address,proto3" json:"address,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *PBGamePlay) Reset() { *m = PBGamePlay{} }
func (m *PBGamePlay) String() string { return proto.CompactTextString(m) }
func (*PBGamePlay) ProtoMessage() {}
func (*PBGamePlay) Descriptor() ([]byte, []int) {
return fileDescriptor_8d22e4ee2313e311, []int{10}
}
func (m *PBGamePlay) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PBGamePlay.Unmarshal(m, b)
}
func (m *PBGamePlay) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_PBGamePlay.Marshal(b, m, deterministic)
}
func (m *PBGamePlay) XXX_Merge(src proto.Message) {
xxx_messageInfo_PBGamePlay.Merge(m, src)
}
func (m *PBGamePlay) XXX_Size() int {
return xxx_messageInfo_PBGamePlay.Size(m)
}
func (m *PBGamePlay) XXX_DiscardUnknown() {
xxx_messageInfo_PBGamePlay.DiscardUnknown(m)
}
var xxx_messageInfo_PBGamePlay proto.InternalMessageInfo
func (m *PBGamePlay) GetGameId() string {
if m != nil {
return m.GameId
}
return ""
}
func (m *PBGamePlay) GetRound() int32 {
if m != nil {
return m.Round
}
return 0
}
func (m *PBGamePlay) GetValue() int64 {
if m != nil {
return m.Value
}
return 0
}
func (m *PBGamePlay) GetAddress() []string {
if m != nil {
return m.Address
}
return nil
}
//根据状态和游戏人数查找
type QueryPBGameListByStatusAndPlayerNum struct {
Status int32 `protobuf:"varint,1,opt,name=status,proto3" json:"status,omitempty"`
......@@ -848,7 +961,7 @@ func (m *QueryPBGameListByStatusAndPlayerNum) Reset() { *m = QueryPBGame
func (m *QueryPBGameListByStatusAndPlayerNum) String() string { return proto.CompactTextString(m) }
func (*QueryPBGameListByStatusAndPlayerNum) ProtoMessage() {}
func (*QueryPBGameListByStatusAndPlayerNum) Descriptor() ([]byte, []int) {
return fileDescriptor_8d22e4ee2313e311, []int{10}
return fileDescriptor_8d22e4ee2313e311, []int{11}
}
func (m *QueryPBGameListByStatusAndPlayerNum) XXX_Unmarshal(b []byte) error {
......@@ -904,7 +1017,7 @@ func (m *PBGameRecord) Reset() { *m = PBGameRecord{} }
func (m *PBGameRecord) String() string { return proto.CompactTextString(m) }
func (*PBGameRecord) ProtoMessage() {}
func (*PBGameRecord) Descriptor() ([]byte, []int) {
return fileDescriptor_8d22e4ee2313e311, []int{11}
return fileDescriptor_8d22e4ee2313e311, []int{12}
}
func (m *PBGameRecord) XXX_Unmarshal(b []byte) error {
......@@ -958,7 +1071,7 @@ func (m *PBGameIndexRecord) Reset() { *m = PBGameIndexRecord{} }
func (m *PBGameIndexRecord) String() string { return proto.CompactTextString(m) }
func (*PBGameIndexRecord) ProtoMessage() {}
func (*PBGameIndexRecord) Descriptor() ([]byte, []int) {
return fileDescriptor_8d22e4ee2313e311, []int{12}
return fileDescriptor_8d22e4ee2313e311, []int{13}
}
func (m *PBGameIndexRecord) XXX_Unmarshal(b []byte) error {
......@@ -1004,7 +1117,7 @@ func (m *PBGameRecords) Reset() { *m = PBGameRecords{} }
func (m *PBGameRecords) String() string { return proto.CompactTextString(m) }
func (*PBGameRecords) ProtoMessage() {}
func (*PBGameRecords) Descriptor() ([]byte, []int) {
return fileDescriptor_8d22e4ee2313e311, []int{13}
return fileDescriptor_8d22e4ee2313e311, []int{14}
}
func (m *PBGameRecords) XXX_Unmarshal(b []byte) error {
......@@ -1043,7 +1156,7 @@ func (m *PBGameIndexRecords) Reset() { *m = PBGameIndexRecords{} }
func (m *PBGameIndexRecords) String() string { return proto.CompactTextString(m) }
func (*PBGameIndexRecords) ProtoMessage() {}
func (*PBGameIndexRecords) Descriptor() ([]byte, []int) {
return fileDescriptor_8d22e4ee2313e311, []int{14}
return fileDescriptor_8d22e4ee2313e311, []int{15}
}
func (m *PBGameIndexRecords) XXX_Unmarshal(b []byte) error {
......@@ -1085,7 +1198,7 @@ func (m *QueryPBGameInfo) Reset() { *m = QueryPBGameInfo{} }
func (m *QueryPBGameInfo) String() string { return proto.CompactTextString(m) }
func (*QueryPBGameInfo) ProtoMessage() {}
func (*QueryPBGameInfo) Descriptor() ([]byte, []int) {
return fileDescriptor_8d22e4ee2313e311, []int{15}
return fileDescriptor_8d22e4ee2313e311, []int{16}
}
func (m *QueryPBGameInfo) XXX_Unmarshal(b []byte) error {
......@@ -1145,7 +1258,7 @@ func (m *ReplyPBGame) Reset() { *m = ReplyPBGame{} }
func (m *ReplyPBGame) String() string { return proto.CompactTextString(m) }
func (*ReplyPBGame) ProtoMessage() {}
func (*ReplyPBGame) Descriptor() ([]byte, []int) {
return fileDescriptor_8d22e4ee2313e311, []int{16}
return fileDescriptor_8d22e4ee2313e311, []int{17}
}
func (m *ReplyPBGame) XXX_Unmarshal(b []byte) error {
......@@ -1184,7 +1297,7 @@ func (m *QueryPBGameInfos) Reset() { *m = QueryPBGameInfos{} }
func (m *QueryPBGameInfos) String() string { return proto.CompactTextString(m) }
func (*QueryPBGameInfos) ProtoMessage() {}
func (*QueryPBGameInfos) Descriptor() ([]byte, []int) {
return fileDescriptor_8d22e4ee2313e311, []int{17}
return fileDescriptor_8d22e4ee2313e311, []int{18}
}
func (m *QueryPBGameInfos) XXX_Unmarshal(b []byte) error {
......@@ -1223,7 +1336,7 @@ func (m *ReplyPBGameList) Reset() { *m = ReplyPBGameList{} }
func (m *ReplyPBGameList) String() string { return proto.CompactTextString(m) }
func (*ReplyPBGameList) ProtoMessage() {}
func (*ReplyPBGameList) Descriptor() ([]byte, []int) {
return fileDescriptor_8d22e4ee2313e311, []int{18}
return fileDescriptor_8d22e4ee2313e311, []int{19}
}
func (m *ReplyPBGameList) XXX_Unmarshal(b []byte) error {
......@@ -1264,7 +1377,7 @@ func (m *QueryPBGameByRound) Reset() { *m = QueryPBGameByRound{} }
func (m *QueryPBGameByRound) String() string { return proto.CompactTextString(m) }
func (*QueryPBGameByRound) ProtoMessage() {}
func (*QueryPBGameByRound) Descriptor() ([]byte, []int) {
return fileDescriptor_8d22e4ee2313e311, []int{19}
return fileDescriptor_8d22e4ee2313e311, []int{20}
}
func (m *QueryPBGameByRound) XXX_Unmarshal(b []byte) error {
......@@ -1317,7 +1430,7 @@ func (m *ReplyPBGameByRound) Reset() { *m = ReplyPBGameByRound{} }
func (m *ReplyPBGameByRound) String() string { return proto.CompactTextString(m) }
func (*ReplyPBGameByRound) ProtoMessage() {}
func (*ReplyPBGameByRound) Descriptor() ([]byte, []int) {
return fileDescriptor_8d22e4ee2313e311, []int{20}
return fileDescriptor_8d22e4ee2313e311, []int{21}
}
func (m *ReplyPBGameByRound) XXX_Unmarshal(b []byte) error {
......@@ -1408,7 +1521,7 @@ func (m *ReceiptPBGame) Reset() { *m = ReceiptPBGame{} }
func (m *ReceiptPBGame) String() string { return proto.CompactTextString(m) }
func (*ReceiptPBGame) ProtoMessage() {}
func (*ReceiptPBGame) Descriptor() ([]byte, []int) {
return fileDescriptor_8d22e4ee2313e311, []int{21}
return fileDescriptor_8d22e4ee2313e311, []int{22}
}
func (m *ReceiptPBGame) XXX_Unmarshal(b []byte) error {
......@@ -1519,7 +1632,7 @@ func (m *PBStartTxReq) Reset() { *m = PBStartTxReq{} }
func (m *PBStartTxReq) String() string { return proto.CompactTextString(m) }
func (*PBStartTxReq) ProtoMessage() {}
func (*PBStartTxReq) Descriptor() ([]byte, []int) {
return fileDescriptor_8d22e4ee2313e311, []int{22}
return fileDescriptor_8d22e4ee2313e311, []int{23}
}
func (m *PBStartTxReq) XXX_Unmarshal(b []byte) error {
......@@ -1573,7 +1686,7 @@ func (m *PBContinueTxReq) Reset() { *m = PBContinueTxReq{} }
func (m *PBContinueTxReq) String() string { return proto.CompactTextString(m) }
func (*PBContinueTxReq) ProtoMessage() {}
func (*PBContinueTxReq) Descriptor() ([]byte, []int) {
return fileDescriptor_8d22e4ee2313e311, []int{23}
return fileDescriptor_8d22e4ee2313e311, []int{24}
}
func (m *PBContinueTxReq) XXX_Unmarshal(b []byte) error {
......@@ -1620,7 +1733,7 @@ func (m *PBQuitTxReq) Reset() { *m = PBQuitTxReq{} }
func (m *PBQuitTxReq) String() string { return proto.CompactTextString(m) }
func (*PBQuitTxReq) ProtoMessage() {}
func (*PBQuitTxReq) Descriptor() ([]byte, []int) {
return fileDescriptor_8d22e4ee2313e311, []int{24}
return fileDescriptor_8d22e4ee2313e311, []int{25}
}
func (m *PBQuitTxReq) XXX_Unmarshal(b []byte) error {
......@@ -1667,7 +1780,7 @@ func (m *PBQueryReq) Reset() { *m = PBQueryReq{} }
func (m *PBQueryReq) String() string { return proto.CompactTextString(m) }
func (*PBQueryReq) ProtoMessage() {}
func (*PBQueryReq) Descriptor() ([]byte, []int) {
return fileDescriptor_8d22e4ee2313e311, []int{25}
return fileDescriptor_8d22e4ee2313e311, []int{26}
}
func (m *PBQueryReq) XXX_Unmarshal(b []byte) error {
......@@ -1713,6 +1826,7 @@ func init() {
proto.RegisterType((*PBGameContinue)(nil), "types.PBGameContinue")
proto.RegisterType((*PBGameQuit)(nil), "types.PBGameQuit")
proto.RegisterType((*PBGameQuery)(nil), "types.PBGameQuery")
proto.RegisterType((*PBGamePlay)(nil), "types.PBGamePlay")
proto.RegisterType((*QueryPBGameListByStatusAndPlayerNum)(nil), "types.QueryPBGameListByStatusAndPlayerNum")
proto.RegisterType((*PBGameRecord)(nil), "types.PBGameRecord")
proto.RegisterType((*PBGameIndexRecord)(nil), "types.PBGameIndexRecord")
......@@ -1734,69 +1848,73 @@ func init() {
func init() { proto.RegisterFile("pokerbull.proto", fileDescriptor_8d22e4ee2313e311) }
var fileDescriptor_8d22e4ee2313e311 = []byte{
// 1021 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0x4b, 0x6f, 0x23, 0x45,
0x10, 0xde, 0xb1, 0x3d, 0x7e, 0xd4, 0x6c, 0xec, 0xa4, 0x81, 0xa8, 0x85, 0x10, 0xb2, 0x66, 0xc3,
0xae, 0x41, 0x90, 0x83, 0x23, 0x81, 0x56, 0x48, 0x48, 0x36, 0x07, 0x1c, 0x69, 0x85, 0x9c, 0xce,
0x4a, 0x7b, 0x9e, 0xf5, 0xf4, 0x66, 0x47, 0x3b, 0x19, 0x3b, 0xf3, 0xc8, 0xc6, 0x57, 0xee, 0xfc,
0x0a, 0x0e, 0xfc, 0x2a, 0x6e, 0xfc, 0x10, 0xd4, 0x55, 0xdd, 0x33, 0x3d, 0x13, 0x9b, 0x10, 0x6e,
0x5d, 0x8f, 0xae, 0xae, 0x57, 0x7f, 0x55, 0x30, 0xda, 0xac, 0x3f, 0xc8, 0xf4, 0x6d, 0x11, 0xc7,
0xa7, 0x9b, 0x74, 0x9d, 0xaf, 0x99, 0x9b, 0x6f, 0x37, 0x32, 0xf3, 0x7f, 0xef, 0xc0, 0x60, 0xa9,
0x44, 0xf3, 0x22, 0x8e, 0xd9, 0x31, 0x74, 0xaf, 0x82, 0x6b, 0x79, 0x1e, 0x72, 0x67, 0xec, 0x4c,
0x06, 0x42, 0x53, 0x8a, 0x9f, 0xe5, 0x41, 0x5e, 0x64, 0xbc, 0x35, 0x76, 0x26, 0xae, 0xd0, 0x14,
0xfb, 0x02, 0x06, 0x59, 0x1e, 0xa4, 0xf9, 0xeb, 0xe8, 0x5a, 0xf2, 0xf6, 0xd8, 0x99, 0xb4, 0x45,
0xc5, 0x60, 0x63, 0xf0, 0x88, 0xb8, 0x5b, 0x04, 0xd9, 0x7b, 0xde, 0x41, 0x93, 0x36, 0x8b, 0x7d,
0x0a, 0xee, 0x6d, 0x10, 0x17, 0x92, 0xbb, 0x78, 0x97, 0x08, 0x76, 0x02, 0x2e, 0x7a, 0xcb, 0xbb,
0x63, 0x67, 0xe2, 0x4d, 0x87, 0xa7, 0xe8, 0xea, 0xe9, 0x72, 0x8e, 0x8e, 0x0a, 0x12, 0xb2, 0xaf,
0xa1, 0xb7, 0x89, 0x83, 0xad, 0x4c, 0x33, 0xde, 0x1b, 0xb7, 0x27, 0xde, 0x74, 0x54, 0xe9, 0x21,
0x5f, 0x18, 0xb9, 0x72, 0x93, 0x8e, 0xbf, 0x16, 0xd7, 0xbc, 0x8f, 0x11, 0x54, 0x0c, 0x65, 0x28,
0x95, 0x59, 0x11, 0xe7, 0x19, 0x1f, 0x34, 0x0c, 0x09, 0xe4, 0x0b, 0x23, 0x57, 0xfe, 0x46, 0x49,
0x28, 0xef, 0x38, 0x90, 0xbf, 0x48, 0xa0, 0xf9, 0x54, 0xde, 0x9e, 0xa3, 0xc4, 0xa3, 0x2c, 0x94,
0x0c, 0xf6, 0x39, 0xf4, 0x6f, 0x8a, 0x88, 0x52, 0xf4, 0x14, 0x85, 0x25, 0xcd, 0xbe, 0x04, 0xc0,
0x33, 0x25, 0xe8, 0x00, 0x13, 0x64, 0x71, 0x94, 0x3c, 0x94, 0x41, 0x2c, 0xd3, 0x59, 0x18, 0xa6,
0x7c, 0x48, 0xf2, 0x8a, 0xa3, 0x5e, 0x8e, 0xb2, 0x37, 0x41, 0x94, 0x47, 0xc9, 0x15, 0x1f, 0x8d,
0x9d, 0x49, 0x5f, 0x54, 0x0c, 0xed, 0xd7, 0x25, 0x15, 0xee, 0x50, 0x87, 0x6d, 0x18, 0x2a, 0x96,
0x74, 0x5d, 0x24, 0x21, 0x3f, 0x42, 0x09, 0x11, 0xfe, 0x6f, 0x0e, 0x74, 0x97, 0xf3, 0x45, 0x90,
0x84, 0x4a, 0x61, 0x15, 0xa4, 0x61, 0xc6, 0x9d, 0x71, 0x5b, 0x29, 0x20, 0xa1, 0x5a, 0x81, 0xb2,
0x61, 0x5a, 0x81, 0x28, 0xc6, 0xa1, 0x17, 0x84, 0x61, 0x2a, 0xb3, 0x0c, 0x1b, 0x61, 0x20, 0x0c,
0x89, 0x49, 0xcb, 0xde, 0x44, 0x09, 0x36, 0x40, 0x5f, 0x10, 0xa1, 0xd2, 0x12, 0xcb, 0x5b, 0x99,
0x06, 0x57, 0x54, 0x7d, 0x57, 0x94, 0xb4, 0xff, 0x11, 0xfa, 0xa6, 0x88, 0xec, 0x19, 0xb8, 0xef,
0x83, 0x44, 0x7b, 0xe1, 0x4d, 0x0f, 0xca, 0xda, 0x28, 0x1f, 0x05, 0xc9, 0xec, 0xc7, 0x5b, 0xf5,
0xc7, 0x8f, 0xa1, 0x9b, 0x53, 0x76, 0xa9, 0x3d, 0x35, 0x85, 0xd1, 0xcb, 0x20, 0xdc, 0x1a, 0xa7,
0x90, 0xf0, 0xff, 0x70, 0xd4, 0xcb, 0x54, 0xf5, 0xff, 0xf6, 0xf2, 0x31, 0x74, 0x3f, 0x46, 0x49,
0x22, 0x53, 0xfd, 0xb0, 0xa6, 0x6a, 0xe1, 0xb5, 0xeb, 0xe1, 0xa9, 0x3b, 0x54, 0x43, 0xfd, 0x25,
0x34, 0xc5, 0x9e, 0xc3, 0x90, 0x4e, 0xaf, 0xea, 0x89, 0x69, 0x70, 0xfd, 0x97, 0xd0, 0xd3, 0x7f,
0x61, 0x4f, 0x8d, 0x38, 0xf4, 0x36, 0xeb, 0x28, 0xc9, 0xb5, 0x57, 0xae, 0x30, 0xa4, 0xff, 0x97,
0x03, 0x4f, 0x97, 0xf3, 0x5f, 0x82, 0x6b, 0x39, 0x5b, 0xe5, 0xd1, 0x3a, 0x61, 0xdf, 0x80, 0x8b,
0x1f, 0x12, 0x3f, 0xbc, 0x37, 0x65, 0x65, 0x90, 0x4a, 0xe7, 0x52, 0x49, 0x16, 0x4f, 0x04, 0xa9,
0xb0, 0x33, 0xe8, 0xaf, 0xd6, 0x49, 0x1e, 0x25, 0x85, 0x44, 0xbb, 0xde, 0xf4, 0xb3, 0x9a, 0xfa,
0xcf, 0x5a, 0xb8, 0x78, 0x22, 0x4a, 0x45, 0xf6, 0x02, 0x3a, 0xaa, 0xa1, 0x31, 0x09, 0xde, 0xf4,
0xa8, 0x76, 0xe1, 0xa2, 0x88, 0x94, 0x79, 0x54, 0x50, 0x9e, 0xdc, 0x14, 0x32, 0xa5, 0x8a, 0x34,
0x3d, 0xb9, 0x50, 0x12, 0xe5, 0x09, 0xaa, 0xb0, 0x21, 0xb4, 0xf2, 0x2d, 0x7e, 0x42, 0x57, 0xb4,
0xf2, 0xed, 0xbc, 0xa7, 0x71, 0xc4, 0x9f, 0x81, 0x67, 0xb9, 0x5e, 0xe1, 0x8b, 0x63, 0xe3, 0x4b,
0x0d, 0x0e, 0x5a, 0x0d, 0x38, 0xf0, 0x27, 0x30, 0xac, 0x87, 0xb3, 0x0f, 0x15, 0xfd, 0x13, 0x80,
0x2a, 0x8e, 0xbd, 0x5a, 0x5f, 0x19, 0x97, 0x30, 0x86, 0xbd, 0x6a, 0x37, 0xf0, 0x0c, 0x15, 0x48,
0xf7, 0x55, 0x94, 0xe5, 0xf3, 0x2d, 0xfd, 0xd4, 0x59, 0x12, 0x2e, 0x4b, 0xb0, 0xaa, 0x90, 0xd8,
0x69, 0x22, 0xf1, 0xfe, 0x98, 0x2a, 0xdc, 0x6a, 0x5b, 0xb8, 0xe5, 0xbf, 0x36, 0xbd, 0x20, 0xe4,
0x6a, 0x9d, 0x86, 0x8f, 0x46, 0xff, 0xdd, 0x56, 0x67, 0x70, 0x44, 0x56, 0x11, 0xfe, 0x1e, 0x30,
0x5d, 0x9a, 0x68, 0xd9, 0x26, 0x7e, 0x82, 0x03, 0xdb, 0xb1, 0x8c, 0x7d, 0xa7, 0x20, 0x1a, 0x8f,
0xfa, 0x33, 0x7e, 0x52, 0xeb, 0x0e, 0x52, 0x13, 0x46, 0xc7, 0x5f, 0x00, 0xbb, 0xe7, 0x42, 0xc6,
0xa6, 0x4d, 0x23, 0xbc, 0x66, 0xc4, 0xd2, 0xad, 0x2c, 0x7d, 0x80, 0x91, 0x55, 0x95, 0xf3, 0xe4,
0xdd, 0x7a, 0x6f, 0x28, 0x0c, 0x3a, 0x0a, 0x74, 0x34, 0x0e, 0xe0, 0xd9, 0xca, 0x5c, 0x7b, 0x77,
0xe6, 0x3a, 0x76, 0xd8, 0x67, 0xe0, 0x09, 0xb9, 0x89, 0xf5, 0x63, 0xec, 0x04, 0x3a, 0xca, 0xb4,
0xfe, 0x99, 0x87, 0xc6, 0x59, 0x33, 0xac, 0x05, 0x4a, 0xfd, 0x6f, 0xe1, 0xb0, 0xe1, 0x21, 0xfe,
0x7f, 0x72, 0x8a, 0x22, 0x1d, 0x08, 0x43, 0xfa, 0x2f, 0x61, 0x64, 0x3d, 0xa1, 0xba, 0x8c, 0x3d,
0x07, 0x57, 0x49, 0x4d, 0x52, 0xee, 0xbf, 0x43, 0x62, 0x7f, 0x0e, 0xcc, 0x7a, 0x68, 0xbe, 0x15,
0x6a, 0x5e, 0xfc, 0x5b, 0x61, 0x69, 0xba, 0xb4, 0xec, 0xe9, 0xf2, 0xb7, 0x03, 0xcc, 0x7a, 0xff,
0x21, 0x23, 0xfb, 0x1a, 0xef, 0x45, 0x39, 0x83, 0x08, 0x55, 0xee, 0x0d, 0x6c, 0x33, 0x94, 0x6a,
0xf3, 0xb1, 0xd3, 0x9c, 0x8f, 0xbb, 0xb7, 0x0f, 0x6b, 0xaf, 0xe8, 0x3e, 0xb0, 0x57, 0xe0, 0x2c,
0xcc, 0x8b, 0x34, 0xe1, 0x3d, 0x1a, 0x2e, 0x44, 0xf9, 0x7f, 0xb6, 0xe0, 0x40, 0xc8, 0x95, 0x8c,
0x36, 0xb9, 0xae, 0xe5, 0x63, 0x23, 0x34, 0xcd, 0xd4, 0xb6, 0x9a, 0x69, 0x67, 0xd3, 0xd4, 0x97,
0x0f, 0xb7, 0xb9, 0x7c, 0xd4, 0x60, 0xa1, 0xbb, 0x03, 0x16, 0x28, 0x01, 0xbd, 0x06, 0x3c, 0x56,
0x49, 0xeb, 0x37, 0x93, 0xc6, 0xab, 0xf4, 0x0c, 0xa8, 0xb7, 0xec, 0x2d, 0xab, 0x5c, 0x37, 0x60,
0xef, 0xba, 0xe1, 0xd9, 0x0d, 0x81, 0x10, 0x74, 0x49, 0x1b, 0xa1, 0x90, 0x37, 0xff, 0x07, 0xb0,
0xd9, 0x21, 0xb4, 0xdf, 0x49, 0xb3, 0x7e, 0xaa, 0xa3, 0xff, 0x23, 0x8c, 0x96, 0x73, 0x03, 0xdf,
0x64, 0x78, 0x5f, 0x01, 0xf4, 0xe5, 0x56, 0x75, 0xf9, 0x07, 0x85, 0xd7, 0x17, 0xb8, 0x83, 0x3d,
0xee, 0xe2, 0xf7, 0x6a, 0x1c, 0xe0, 0x17, 0x79, 0xd4, 0xbd, 0xb7, 0x5d, 0x5c, 0xc8, 0xcf, 0xfe,
0x09, 0x00, 0x00, 0xff, 0xff, 0xda, 0x14, 0x34, 0x44, 0xa3, 0x0b, 0x00, 0x00,
// 1081 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0x4f, 0x6f, 0xe3, 0x44,
0x14, 0x5f, 0xdb, 0xb1, 0x93, 0x3c, 0x6f, 0x9b, 0x76, 0x80, 0x6a, 0x84, 0x10, 0x8a, 0xbc, 0x65,
0x37, 0x20, 0xe8, 0x21, 0x95, 0x40, 0x2b, 0x24, 0xa4, 0x86, 0x03, 0xa9, 0xb4, 0x42, 0xe9, 0x74,
0xa5, 0x3d, 0x7b, 0xe3, 0xd9, 0xd6, 0xac, 0xe3, 0xa4, 0xfe, 0x53, 0x36, 0x5f, 0x80, 0x1b, 0x47,
0xee, 0x48, 0x1c, 0xf8, 0x62, 0x7c, 0x10, 0x34, 0x6f, 0x66, 0xec, 0xb1, 0x1b, 0xab, 0x84, 0x9b,
0xdf, 0x9f, 0x79, 0xf3, 0x7b, 0x6f, 0xde, 0xfc, 0xde, 0x18, 0x46, 0x9b, 0xf5, 0x7b, 0x9e, 0xbd,
0x2d, 0x93, 0xe4, 0x6c, 0x93, 0xad, 0x8b, 0x35, 0x71, 0x8b, 0xed, 0x86, 0xe7, 0xc1, 0xef, 0x3d,
0x18, 0x2e, 0x84, 0x69, 0x56, 0x26, 0x09, 0x39, 0x01, 0xef, 0x26, 0x5c, 0xf1, 0xcb, 0x88, 0x5a,
0x63, 0x6b, 0x32, 0x64, 0x4a, 0x12, 0xfa, 0xbc, 0x08, 0x8b, 0x32, 0xa7, 0xf6, 0xd8, 0x9a, 0xb8,
0x4c, 0x49, 0xe4, 0x33, 0x18, 0xe6, 0x45, 0x98, 0x15, 0xaf, 0xe3, 0x15, 0xa7, 0x0e, 0x2e, 0xa9,
0x15, 0x64, 0x0c, 0xbe, 0x14, 0x3e, 0xcc, 0xc3, 0xfc, 0x96, 0xf6, 0xd0, 0x6e, 0xaa, 0xc8, 0xc7,
0xe0, 0xde, 0x87, 0x49, 0xc9, 0xa9, 0x3b, 0xb6, 0x26, 0x0e, 0x93, 0x02, 0x39, 0x05, 0x17, 0xd1,
0x52, 0x6f, 0x6c, 0x4d, 0xfc, 0xe9, 0xe1, 0x19, 0x42, 0x3d, 0x5b, 0xcc, 0x10, 0x28, 0x93, 0x46,
0xf2, 0x25, 0xf4, 0x37, 0x49, 0xb8, 0xe5, 0x59, 0x4e, 0xfb, 0x63, 0x67, 0xe2, 0x4f, 0x47, 0xb5,
0x1f, 0xea, 0x99, 0xb6, 0x0b, 0x98, 0xf2, 0xf3, 0xe7, 0x72, 0x45, 0x07, 0x98, 0x41, 0xad, 0x10,
0x81, 0x32, 0x9e, 0x97, 0x49, 0x91, 0xd3, 0x61, 0x2b, 0x10, 0x43, 0x3d, 0xd3, 0x76, 0x81, 0x37,
0x4e, 0x23, 0xfe, 0x81, 0x82, 0xc4, 0x8b, 0x02, 0x86, 0xcf, 0xf8, 0xfd, 0x25, 0x5a, 0x7c, 0xb4,
0xd4, 0x0a, 0xf2, 0x29, 0x0c, 0xee, 0xca, 0x58, 0x96, 0xe8, 0x29, 0x96, 0xa0, 0x92, 0xc9, 0xe7,
0x00, 0xf8, 0x2d, 0x0b, 0x74, 0x80, 0x56, 0x43, 0x23, 0xec, 0x11, 0x0f, 0x13, 0x9e, 0x5d, 0x44,
0x51, 0x46, 0x0f, 0xa5, 0xbd, 0xd6, 0x88, 0x9d, 0xe3, 0xfc, 0x4d, 0x18, 0x17, 0x71, 0x7a, 0x43,
0x47, 0x63, 0x6b, 0x32, 0x60, 0xb5, 0x42, 0xe1, 0xba, 0x96, 0x07, 0x77, 0xa4, 0xd2, 0xd6, 0x0a,
0x91, 0x4b, 0xb6, 0x2e, 0xd3, 0x88, 0x1e, 0xa3, 0x45, 0x0a, 0xc1, 0x9f, 0x16, 0x78, 0x8b, 0xd9,
0x3c, 0x4c, 0x23, 0xe1, 0xb0, 0x0c, 0xb3, 0x28, 0xa7, 0xd6, 0xd8, 0x11, 0x0e, 0x28, 0x88, 0x56,
0x90, 0xd5, 0xd0, 0xad, 0x20, 0x25, 0x42, 0xa1, 0x1f, 0x46, 0x51, 0xc6, 0xf3, 0x5c, 0x35, 0x82,
0x16, 0xb1, 0x68, 0xf9, 0x9b, 0x38, 0xc5, 0x06, 0x18, 0x30, 0x29, 0x88, 0xb2, 0x24, 0xfc, 0x9e,
0x67, 0xe1, 0x8d, 0x3c, 0x7d, 0x97, 0x55, 0xb2, 0x00, 0x8e, 0x68, 0xb0, 0x66, 0x9e, 0x6c, 0xab,
0x4a, 0x11, 0xfc, 0x61, 0xc1, 0x40, 0x9f, 0x31, 0x79, 0x06, 0xee, 0x6d, 0x98, 0x2a, 0x90, 0xfe,
0xf4, 0xa0, 0x3a, 0x3a, 0x91, 0x02, 0x93, 0x36, 0x13, 0x9b, 0xdd, 0xc4, 0x76, 0x02, 0x5e, 0x21,
0x8b, 0xef, 0xe0, 0xb9, 0x29, 0x09, 0x8b, 0xc3, 0xc3, 0x68, 0xab, 0x31, 0xa3, 0x20, 0x70, 0xad,
0xc2, 0x62, 0x79, 0x8b, 0xb8, 0x5c, 0x89, 0xab, 0x52, 0x04, 0x7f, 0x21, 0x2e, 0xd9, 0x32, 0xff,
0x0d, 0xd7, 0x09, 0x78, 0xbf, 0xc6, 0x69, 0xca, 0x33, 0x05, 0x4b, 0x49, 0x8d, 0xda, 0x38, 0xad,
0xda, 0x9c, 0x80, 0x27, 0x1b, 0x40, 0xdd, 0x27, 0x25, 0x91, 0xe7, 0x70, 0x28, 0xbf, 0x5e, 0x35,
0xab, 0xda, 0xd2, 0x06, 0x2f, 0xa1, 0xaf, 0x2e, 0x52, 0xc7, 0x01, 0x53, 0xe8, 0x6f, 0xd6, 0x71,
0x5a, 0x28, 0x54, 0x2e, 0xd3, 0x62, 0xf0, 0x9b, 0x0d, 0x4f, 0x17, 0xb3, 0x9f, 0xc2, 0x15, 0xbf,
0x58, 0x16, 0xf1, 0x3a, 0x25, 0x5f, 0x81, 0x8b, 0xb7, 0x19, 0xd9, 0xc2, 0x9f, 0x92, 0x2a, 0x49,
0xe1, 0x73, 0x2d, 0x2c, 0xf3, 0x27, 0x4c, 0xba, 0x90, 0x73, 0x18, 0x2c, 0xd7, 0x69, 0x11, 0xa7,
0x25, 0xc7, 0xb8, 0xfe, 0xf4, 0x93, 0x86, 0xfb, 0x8f, 0xca, 0x38, 0x7f, 0xc2, 0x2a, 0x47, 0xf2,
0x02, 0x7a, 0xe2, 0x36, 0x60, 0x11, 0xfc, 0xe9, 0x71, 0x63, 0xc1, 0x55, 0x19, 0x8b, 0xf0, 0xe8,
0x20, 0x90, 0xdc, 0x95, 0x3c, 0x93, 0xe7, 0xd5, 0x46, 0x72, 0x25, 0x2c, 0x02, 0x09, 0xba, 0x88,
0xa0, 0xe2, 0xf2, 0x63, 0x7d, 0xda, 0x41, 0x45, 0x57, 0x89, 0xa0, 0xc2, 0x81, 0x1c, 0x82, 0x5d,
0x6c, 0xf1, 0xaa, 0xbb, 0xcc, 0x2e, 0xb6, 0xb3, 0xbe, 0x62, 0xab, 0xe0, 0x02, 0x7c, 0x23, 0xc7,
0x9a, 0xc5, 0x2c, 0x93, 0xc5, 0x1a, 0xa4, 0x63, 0xb7, 0x48, 0x27, 0x98, 0xc0, 0x61, 0x33, 0xef,
0x2e, 0xee, 0x0d, 0x4e, 0x01, 0xea, 0x84, 0x3b, 0xbd, 0xbe, 0xd0, 0x90, 0x30, 0xd9, 0x4e, 0xb7,
0x5f, 0x74, 0x30, 0x91, 0x68, 0x27, 0xdd, 0x57, 0xd4, 0x60, 0x1b, 0xd4, 0x50, 0xa7, 0xe9, 0x98,
0x69, 0x1a, 0x77, 0xab, 0x37, 0x76, 0x8c, 0xbb, 0x15, 0xdc, 0xc1, 0x33, 0x04, 0x23, 0x37, 0x7c,
0x15, 0xe7, 0xc5, 0x6c, 0x2b, 0xb9, 0xe7, 0x22, 0x8d, 0x16, 0x15, 0xfd, 0xd6, 0xb3, 0xc5, 0x6a,
0xcf, 0x96, 0xee, 0xfa, 0xd5, 0x4c, 0xec, 0x18, 0x4c, 0x1c, 0xbc, 0xd6, 0x0d, 0xca, 0xf8, 0x72,
0x9d, 0x45, 0x7b, 0xcf, 0xb3, 0xdd, 0x51, 0x2f, 0xe0, 0x58, 0x46, 0x45, 0x42, 0x7f, 0x24, 0x74,
0x15, 0xc2, 0x36, 0x43, 0xfc, 0x00, 0x07, 0x26, 0xb0, 0x9c, 0x7c, 0x23, 0x86, 0x0e, 0x7e, 0x2a,
0x86, 0xf8, 0xa8, 0xd1, 0x87, 0xd2, 0x8d, 0x69, 0x9f, 0x60, 0x0e, 0xe4, 0x01, 0x84, 0x9c, 0x4c,
0xdb, 0x41, 0x68, 0x23, 0x88, 0xe1, 0x5b, 0x47, 0x7a, 0x0f, 0x23, 0xe3, 0x54, 0x2e, 0xd3, 0x77,
0xeb, 0xce, 0x54, 0x08, 0xf4, 0xc4, 0x59, 0x2a, 0x72, 0xc2, 0x6f, 0xa3, 0x72, 0xce, 0xee, 0xca,
0xf5, 0xcc, 0xb4, 0xcf, 0xc1, 0x67, 0x7c, 0x93, 0xa8, 0xcd, 0xc8, 0x29, 0xf4, 0x44, 0x68, 0x45,
0x17, 0x47, 0x1a, 0xac, 0x7e, 0x7e, 0x30, 0xb4, 0x06, 0x5f, 0xc3, 0x51, 0x0b, 0x21, 0x92, 0x92,
0x04, 0x25, 0x33, 0x1d, 0x32, 0x2d, 0x06, 0x2f, 0x61, 0x64, 0x6c, 0x21, 0xba, 0x8c, 0x3c, 0x07,
0x57, 0x58, 0x75, 0x51, 0x1e, 0xee, 0x23, 0xcd, 0xc1, 0x0c, 0x88, 0xb1, 0xd1, 0x6c, 0xcb, 0xb0,
0xcd, 0xf7, 0xba, 0x14, 0xc1, 0x3f, 0x16, 0x10, 0x63, 0xff, 0xc7, 0x82, 0x74, 0x35, 0xde, 0x8b,
0x6a, 0xaa, 0x4a, 0xaa, 0x7b, 0xf0, 0x04, 0xd1, 0x63, 0xb6, 0x31, 0xf1, 0x7b, 0xed, 0x89, 0xbf,
0xfb, 0x3d, 0x65, 0xbc, 0x94, 0xbc, 0x47, 0x5e, 0x4a, 0x38, 0xdd, 0x8b, 0x32, 0x4b, 0x69, 0x5f,
0xce, 0x43, 0x29, 0x05, 0x7f, 0xdb, 0x70, 0xc0, 0xf8, 0x92, 0xc7, 0x9b, 0x42, 0x9d, 0xe5, 0xbe,
0x19, 0xea, 0x66, 0x72, 0x8c, 0x66, 0xda, 0xd9, 0x34, 0xcd, 0xe7, 0x94, 0xdb, 0x7e, 0x4e, 0x35,
0x68, 0xc1, 0xdb, 0x41, 0x0b, 0xb2, 0x00, 0xfd, 0x16, 0x15, 0xd7, 0x45, 0x1b, 0xb4, 0x8b, 0x46,
0xeb, 0xf2, 0x0c, 0x65, 0x6f, 0x99, 0xef, 0xc6, 0xea, 0x01, 0x05, 0x9d, 0x0f, 0x28, 0xdf, 0x6c,
0x08, 0xa4, 0xa0, 0x6b, 0xf9, 0xc6, 0x65, 0xfc, 0xee, 0xff, 0x0c, 0x07, 0x72, 0x04, 0xce, 0x3b,
0xae, 0x79, 0x56, 0x7c, 0x06, 0xdf, 0xc3, 0x68, 0x31, 0xd3, 0xa3, 0x42, 0x06, 0xee, 0x3a, 0x00,
0xb5, 0xd8, 0xae, 0x17, 0x7f, 0x27, 0x66, 0xc3, 0x15, 0xbe, 0x2a, 0xf7, 0x5b, 0xf8, 0xad, 0x98,
0x16, 0x78, 0x45, 0xf6, 0x5a, 0xf7, 0xd6, 0xc3, 0x5f, 0x8c, 0xf3, 0x7f, 0x03, 0x00, 0x00, 0xff,
0xff, 0xb4, 0x58, 0xec, 0xbf, 0x75, 0x0c, 0x00, 0x00,
}
......@@ -46,6 +46,7 @@ func (t *PokerBullType) GetTypeMap() map[string]int32 {
"Continue": PBGameActionContinue,
"Quit": PBGameActionQuit,
"Query": PBGameActionQuery,
"Play": PBGameActionPlay,
}
}
......@@ -56,5 +57,6 @@ func (t *PokerBullType) GetLogMap() map[int64]*types.LogInfo {
TyLogPBGameContinue: {Ty: reflect.TypeOf(ReceiptPBGame{}), Name: "TyLogPBGameContinue"},
TyLogPBGameQuit: {Ty: reflect.TypeOf(ReceiptPBGame{}), Name: "TyLogPBGameQuit"},
TyLogPBGameQuery: {Ty: reflect.TypeOf(ReceiptPBGame{}), Name: "TyLogPBGameQuery"},
TyLogPBGamePlay: {Ty: reflect.TypeOf(ReceiptPBGame{}), Name: "TyLogPBGamePlay"},
}
}
......@@ -47,5 +47,5 @@ func (ticket *Ticket) Query_MinerSourceList(param *types.ReqString) (types.Messa
// Query_RandNumHash query randnumhash
func (ticket *Ticket) Query_RandNumHash(param *types.ReqRandHash) (types.Message, error) {
return ticket.GetRandNum(param.Height, param.BlockNum)
return ticket.GetRandNum(param.Hash, param.BlockNum)
}
......@@ -18,19 +18,20 @@ const (
)
// GetRandNum for ticket executor
func (ticket *Ticket) GetRandNum(height int64, blockNum int64) (types.Message, error) {
tlog.Debug("GetRandNum", "height", height, "blockNum", blockNum)
func (ticket *Ticket) GetRandNum(blockHash []byte, blockNum int64) (types.Message, error) {
tlog.Debug("GetRandNum", "blockHash", blockHash, "blockNum", blockNum)
if blockNum < minBlockNum {
blockNum = minBlockNum
} else if blockNum > maxBlockNum {
blockNum = maxBlockNum
}
if blockNum >= height {
return nil, types.ErrNotFound
if len(blockHash) == 0 {
return nil, types.ErrBlockNotFound
}
txActions, err := ticket.getTxActions(height, blockNum)
txActions, err := ticket.getTxActions(blockHash, blockNum)
if err != nil {
return nil, err
}
......@@ -54,20 +55,36 @@ func (ticket *Ticket) GetRandNum(height int64, blockNum int64) (types.Message, e
return &types.ReplyHash{Hash: modify}, nil
}
func (ticket *Ticket) getTxActions(height int64, blockNum int64) ([]*tickettypes.TicketAction, error) {
func (ticket *Ticket) getTxActions(blockHash []byte, blockNum int64) ([]*tickettypes.TicketAction, error) {
var txActions []*tickettypes.TicketAction
var reqHashes types.ReqHashes
currHash := blockHash
tlog.Debug("getTxActions", "blockHash", blockHash, "blockNum", blockNum)
tlog.Debug("getTxActions", "height", height, "blockNum", blockNum)
//根据blockHash,查询block,循环blockNum
for blockNum > 0 {
req := types.ReqHash{Hash: currHash}
req := &types.ReqBlocks{Start: height - blockNum + 1, End: height, IsDetail: false, Pid: []string{""}}
tempBlock, err := ticket.GetAPI().GetBlockOverview(&req)
if err != nil {
return txActions, err
}
reqHashes.Hashes = append(reqHashes.Hashes, currHash)
currHash = tempBlock.Head.ParentHash
if tempBlock.Head.Height < 0 && blockNum > 1 {
return txActions, types.ErrBlockNotFound
}
blockNum--
}
blockDetails, err := ticket.GetAPI().GetBlocks(req)
blockDetails, err := ticket.GetAPI().GetBlockByHashes(&reqHashes)
if err != nil {
tlog.Error("getTxActions", "height", height, "blockNum", blockNum, "err", err)
tlog.Error("getTxActions", "blockHash", blockHash, "blockNum", blockNum, "err", err)
return txActions, err
}
for _, block := range blockDetails.Items {
//tlog.Debug("getTxActions", "blockHeight", block.Block.Height, "blockhash", block.Block.Hash())
tlog.Debug("getTxActions", "blockHeight", block.Block.Height, "blockhash", block.Block.Hash())
ticketAction, err := ticket.getMinerTx(block.Block)
if err != nil {
return txActions, err
......
......@@ -7,13 +7,13 @@ package commands
import (
"encoding/json"
"fmt"
"math"
"os"
"strconv"
"strings"
"github.com/33cn/chain33/rpc/jsonclient"
rpctypes "github.com/33cn/chain33/rpc/types"
"github.com/33cn/chain33/system/dapp/commands"
"github.com/33cn/chain33/types"
tokenty "github.com/33cn/plugin/plugin/dapp/token/types"
"github.com/spf13/cobra"
......@@ -72,31 +72,7 @@ func addCreateTokenTransferFlags(cmd *cobra.Command) {
}
func createTokenTransfer(cmd *cobra.Command, args []string) {
toAddr, _ := cmd.Flags().GetString("to")
amount, _ := cmd.Flags().GetFloat64("amount")
note, _ := cmd.Flags().GetString("note")
symbol, _ := cmd.Flags().GetString("symbol")
payload := &types.AssetsTransfer{
To: toAddr,
Amount: int64(math.Trunc((amount+0.0000001)*1e4)) * 1e4,
Note: []byte(note),
Cointoken: symbol,
}
data, err := json.Marshal(&payload)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(tokenty.TokenX),
ActionName: "Transfer",
Payload: data,
}
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, nil)
ctx.RunWithoutMarshal()
commands.CreateAssetTransfer(cmd, args, tokenty.TokenX)
}
// CreateTokenTransferExecCmd create raw transfer tx
......@@ -124,41 +100,7 @@ func addCreateTokenSendToExecFlags(cmd *cobra.Command) {
}
func createTokenSendToExec(cmd *cobra.Command, args []string) {
paraName, _ := cmd.Flags().GetString("paraName")
exec, _ := cmd.Flags().GetString("exec")
exec = getRealExecName(paraName, exec)
to, err := GetExecAddr(exec)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
amount, _ := cmd.Flags().GetFloat64("amount")
note, _ := cmd.Flags().GetString("note")
symbol, _ := cmd.Flags().GetString("symbol")
payload := &types.AssetsTransferToExec{
To: to,
Amount: int64(math.Trunc((amount+0.0000001)*1e4)) * 1e4,
Note: []byte(note),
Cointoken: symbol,
ExecName: exec,
}
data, err := json.Marshal(&payload)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(tokenty.TokenX),
ActionName: "TransferToExec",
Payload: data,
}
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, nil)
ctx.RunWithoutMarshal()
commands.CreateAssetSendToExec(cmd, args, tokenty.TokenX)
}
// CreateTokenWithdrawCmd create raw withdraw tx
......@@ -186,40 +128,7 @@ func addCreateTokenWithdrawFlags(cmd *cobra.Command) {
}
func createTokenWithdraw(cmd *cobra.Command, args []string) {
exec, _ := cmd.Flags().GetString("exec")
paraName, _ := cmd.Flags().GetString("paraName")
exec = getRealExecName(paraName, exec)
amount, _ := cmd.Flags().GetFloat64("amount")
note, _ := cmd.Flags().GetString("note")
symbol, _ := cmd.Flags().GetString("symbol")
exec = getRealExecName(paraName, exec)
execAddr, err := GetExecAddr(exec)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
payload := &types.AssetsWithdraw{
To: execAddr,
Amount: int64(math.Trunc((amount+0.0000001)*1e4)) * 1e4,
Note: []byte(note),
Cointoken: symbol,
ExecName: exec,
}
data, err := json.Marshal(&payload)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(tokenty.TokenX),
ActionName: "Withdraw",
Payload: data,
}
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, nil)
ctx.RunWithoutMarshal()
commands.CreateAssetWithdraw(cmd, args, tokenty.TokenX)
}
// GetTokensPreCreatedCmd get precreated tokens
......
......@@ -20,6 +20,11 @@ chain33背后故事: [chain33诞生记](https://mp.weixin.qq.com/s/9g5ZFDKJi9uzR
视频教程: [视频教程](https://chain.33.cn/document/90)
# 感谢
[腾讯玄武实验室](https://github.com/33cn/chain33/issues?utf8=%E2%9C%93&q=label%3A%E8%85%BE%E8%AE%AF%E7%8E%84%E6%AD%A6%E5%AE%9E%E9%AA%8C%E5%AE%A4)
## Building from source
环境要求: Go (version 1.9 or later)
......
......@@ -276,8 +276,8 @@ func (acc *DB) loadAccountsHistory(api client.QueueProtocolAPI, addrs []string,
// GetBalance 获取某个状态下账户余额
func (acc *DB) GetBalance(api client.QueueProtocolAPI, in *types.ReqBalance) ([]*types.Account, error) {
switch in.GetExecer() {
case types.ExecName("coins"):
// load account
if in.AssetExec == in.Execer || "" == in.Execer {
addrs := in.GetAddresses()
var exaddrs []string
for _, addr := range addrs {
......@@ -306,34 +306,35 @@ func (acc *DB) GetBalance(api client.QueueProtocolAPI, in *types.ReqBalance) ([]
}
}
return accounts, nil
default:
execaddress := address.ExecAddress(in.GetExecer())
addrs := in.GetAddresses()
var accounts []*types.Account
for _, addr := range addrs {
var account *types.Account
var err error
if len(in.StateHash) == 0 {
account, err = acc.LoadExecAccountQueue(api, addr, execaddress)
if err != nil {
log.Error("GetBalance", "err", err.Error())
continue
}
} else {
hash, err := common.FromHex(in.StateHash)
if err != nil {
return nil, err
}
account, err = acc.LoadExecAccountHistoryQueue(api, addr, execaddress, hash)
if err != nil {
log.Error("GetBalance", "err", err.Error())
continue
}
}
// load exec account
execaddress := address.ExecAddress(in.GetExecer())
addrs := in.GetAddresses()
var accounts []*types.Account
for _, addr := range addrs {
var account *types.Account
var err error
if len(in.StateHash) == 0 {
account, err = acc.LoadExecAccountQueue(api, addr, execaddress)
if err != nil {
log.Error("GetBalance", "err", err.Error())
continue
}
} else {
hash, err := common.FromHex(in.StateHash)
if err != nil {
return nil, err
}
account, err = acc.LoadExecAccountHistoryQueue(api, addr, execaddress, hash)
if err != nil {
log.Error("GetBalance", "err", err.Error())
continue
}
accounts = append(accounts, account)
}
return accounts, nil
accounts = append(accounts, account)
}
return accounts, nil
}
// GetExecBalance 通过account模块获取地址账户在合约中的余额
......
......@@ -108,21 +108,24 @@ function start_chain33() {
echo "=========== #transfer to miner addr ============="
hash=$(${CLI} send coins transfer -a 10000 -n test -t 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -k CC38546E9E659D15E6B4893F0AB32A06D103931A8230B0BDE71459D2B27D6944)
echo "${hash}"
sleep ${chain33BlockTime}
txs=$(${CLI} tx query_hash -s "${hash}" | jq ".txs")
if [ "${txs}" == "null" ]; then
echo "transferTokenAdmin cannot find tx"
result=$(${CLI} tx query -s "${hash}" | jq '.receipt.tyName')
if [[ ${result} != '"ExecOk"' ]]; then
echo "Failed"
${CLI} tx query -s "${hash}" | jq '.' | cat
exit 1
fi
echo "=========== #transfer to token amdin ============="
hash=$(${CLI} send coins transfer -a 10 -n test -t 1Q8hGLfoGe63efeWa8fJ4Pnukhkngt6poK -k CC38546E9E659D15E6B4893F0AB32A06D103931A8230B0BDE71459D2B27D6944)
echo "${hash}"
sleep ${chain33BlockTime}
txs=$(${CLI} tx query_hash -s "${hash}" | jq ".txs")
if [ "${txs}" == "null" ]; then
echo "transferTokenAdmin cannot find tx"
result=$(${CLI} tx query -s "${hash}" | jq '.receipt.tyName')
if [[ ${result} != '"ExecOk"' ]]; then
echo "Failed"
${CLI} tx query -s "${hash}" | jq '.' | cat
exit 1
fi
......@@ -131,10 +134,12 @@ function start_chain33() {
signData=$(${CLI} wallet sign -d "${rawData}" -k 0xc34b5d9d44ac7b754806f761d3d4d2c4fe5214f6b074c19f069c4f5c2a29c8cc)
hash=$(${CLI} wallet send -d "${signData}")
echo "${hash}"
sleep ${chain33BlockTime}
txs=$(${CLI} tx query_hash -s "${hash}" | jq ".txs")
if [ "${txs}" == "null" ]; then
echo "transferTokenAdmin cannot find tx"
result=$(${CLI} tx query -s "${hash}" | jq '.receipt.tyName')
if [[ ${result} != '"ExecOk"' ]]; then
echo "Failed"
${CLI} tx query -s "${hash}" | jq '.' | cat
exit 1
fi
......
......@@ -121,21 +121,24 @@ function start_chain33() {
echo "=========== #transfer to miner addr ============="
hash=$(${CLI} send coins transfer -a 10000 -n test -t 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -k CC38546E9E659D15E6B4893F0AB32A06D103931A8230B0BDE71459D2B27D6944)
echo "${hash}"
sleep ${chain33BlockTime}
txs=$(${CLI} tx query_hash -s "${hash}" | jq ".txs")
if [ "${txs}" == "null" ]; then
echo "transferTokenAdmin cannot find tx"
result=$(${CLI} tx query -s "${hash}" | jq '.receipt.tyName')
if [[ ${result} != '"ExecOk"' ]]; then
echo "Failed"
${CLI} tx query -s "${hash}" | jq '.' | cat
exit 1
fi
echo "=========== #transfer to token amdin ============="
hash=$(${CLI} send coins transfer -a 10 -n test -t 1Q8hGLfoGe63efeWa8fJ4Pnukhkngt6poK -k CC38546E9E659D15E6B4893F0AB32A06D103931A8230B0BDE71459D2B27D6944)
echo "${hash}"
sleep ${chain33BlockTime}
txs=$(${CLI} tx query_hash -s "${hash}" | jq ".txs")
if [ "${txs}" == "null" ]; then
echo "transferTokenAdmin cannot find tx"
result=$(${CLI} tx query -s "${hash}" | jq '.receipt.tyName')
if [[ ${result} != '"ExecOk"' ]]; then
echo "Failed"
${CLI} tx query -s "${hash}" | jq '.' | cat
exit 1
fi
......@@ -144,10 +147,12 @@ function start_chain33() {
signData=$(${CLI} wallet sign -d "${rawData}" -k 0xc34b5d9d44ac7b754806f761d3d4d2c4fe5214f6b074c19f069c4f5c2a29c8cc)
hash=$(${CLI} wallet send -d "${signData}")
echo "${hash}"
sleep ${chain33BlockTime}
txs=$(${CLI} tx query_hash -s "${hash}" | jq ".txs")
if [ "${txs}" == "null" ]; then
echo "transferTokenAdmin cannot find tx"
result=$(${CLI} tx query -s "${hash}" | jq '.receipt.tyName')
if [[ ${result} != '"ExecOk"' ]]; then
echo "Failed"
${CLI} tx query -s "${hash}" | jq '.' | cat
exit 1
fi
......
......@@ -206,7 +206,20 @@ func (c *channelClient) GetAddrOverview(parm *types.ReqAddr) (*types.AddrOvervie
// GetBalance get balance
func (c *channelClient) GetBalance(in *types.ReqBalance) ([]*types.Account, error) {
return c.accountdb.GetBalance(c.QueueProtocolAPI, in)
// in.AssetExec & in.AssetSymbol 新增参数,
// 不填时兼容原来的调用
if in.AssetExec == "" || in.AssetSymbol == "" {
in.AssetSymbol = "bty"
in.AssetExec = "coins"
return c.accountdb.GetBalance(c.QueueProtocolAPI, in)
}
acc, err := account.NewAccountDB(in.AssetExec, in.AssetSymbol, nil)
if err != nil {
log.Error("GetBalance", "Error", err.Error())
return nil, err
}
return acc.GetBalance(c.QueueProtocolAPI, in)
}
// GetAllExecBalance get balance of exec
......@@ -288,3 +301,49 @@ func (c *channelClient) GetExecBalance(in *types.ReqGetExecBalance) (*types.Repl
}
return resp, nil
}
// GetAssetBalance 通用的获得资产的接口
func (c *channelClient) GetAssetBalance(in *types.ReqBalance) ([]*types.Account, error) {
if in.AssetSymbol == "" || in.AssetExec == "" {
return nil, types.ErrInvalidParam
}
acc, err := account.NewAccountDB(in.AssetExec, in.AssetSymbol, nil)
if err != nil {
return nil, err
}
// load balance
if in.AssetExec == in.Execer || in.Execer == "" {
addrs := in.GetAddresses()
var queryAddrs []string
for _, addr := range addrs {
if err := address.CheckAddress(addr); err != nil {
addr = string(acc.AccountKey(addr))
}
queryAddrs = append(queryAddrs, addr)
}
accounts, err := acc.LoadAccounts(c.QueueProtocolAPI, queryAddrs)
if err != nil {
log.Error("GetAssetBalance", "err", err.Error(), "exec", in.AssetExec, "symbol", in.AssetSymbol,
"address", queryAddrs)
return nil, err
}
return accounts, nil
}
// load exec balance
execaddress := address.ExecAddress(in.GetExecer())
addrs := in.GetAddresses()
var accounts []*types.Account
for _, addr := range addrs {
acc, err := acc.LoadExecAccountQueue(c.QueueProtocolAPI, addr, execaddress)
if err != nil {
log.Error("GetAssetBalance for exector", "err", err.Error(), "exec", in.AssetExec,
"symbol", in.AssetSymbol, "address", addr, "where", in.Execer)
continue
}
accounts = append(accounts, acc)
}
return accounts, nil
}
......@@ -361,3 +361,66 @@ func TestChannelClient_GetBalance(t *testing.T) {
// assert.NotNil(t, data)
// assert.Nil(t, err)
// }
func testChannelClient_GetAssetBalanceCoin(t *testing.T) {
api := new(mocks.QueueProtocolAPI)
db := new(account.DB)
client := &channelClient{
QueueProtocolAPI: api,
accountdb: db,
}
head := &types.Header{StateHash: []byte("sdfadasds")}
api.On("GetLastHeader").Return(head, nil)
var acc = &types.Account{Addr: "1Jn2qu84Z1SUUosWjySggBS9pKWdAP3tZt", Balance: 100}
accv := types.Encode(acc)
storevalue := &types.StoreReplyValue{}
storevalue.Values = append(storevalue.Values, accv)
api.On("StoreGet", mock.Anything).Return(storevalue, nil)
var addrs = []string{"1Jn2qu84Z1SUUosWjySggBS9pKWdAP3tZt"}
var in = &types.ReqBalance{
AssetSymbol: "bty",
AssetExec: "coins",
Execer: "coins",
Addresses: addrs,
}
data, err := client.GetAssetBalance(in)
assert.Nil(t, err)
assert.Equal(t, acc.Addr, data[0].Addr)
}
func testChannelClient_GetAssetBalanceOther(t *testing.T) {
api := new(mocks.QueueProtocolAPI)
db := new(account.DB)
client := &channelClient{
QueueProtocolAPI: api,
accountdb: db,
}
head := &types.Header{StateHash: []byte("sdfadasds")}
api.On("GetLastHeader").Return(head, nil)
var acc = &types.Account{Addr: "1Jn2qu84Z1SUUosWjySggBS9pKWdAP3tZt", Balance: 100}
accv := types.Encode(acc)
storevalue := &types.StoreReplyValue{}
storevalue.Values = append(storevalue.Values, accv)
api.On("StoreGet", mock.Anything).Return(storevalue, nil)
var addrs = []string{"1Jn2qu84Z1SUUosWjySggBS9pKWdAP3tZt"}
var in = &types.ReqBalance{
AssetSymbol: "bty",
AssetExec: "coins",
Execer: types.ExecName("ticket"),
Addresses: addrs,
}
data, err := client.GetAssetBalance(in)
assert.Nil(t, err)
assert.Equal(t, acc.Addr, data[0].Addr)
}
func TestChannelClient_GetAssetBalance(t *testing.T) {
testChannelClient_GetAssetBalanceCoin(t)
testChannelClient_GetAssetBalanceOther(t)
}
......@@ -741,19 +741,12 @@ func (c *Chain33) GetWalletStatus(in types.ReqNil, result *interface{}) error {
// GetBalance get balance
func (c *Chain33) GetBalance(in types.ReqBalance, result *interface{}) error {
balances, err := c.cli.GetBalance(&in)
if err != nil {
return err
}
var accounts []*rpctypes.Account
for _, balance := range balances {
accounts = append(accounts, &rpctypes.Account{Addr: balance.GetAddr(),
Balance: balance.GetBalance(),
Currency: balance.GetCurrency(),
Frozen: balance.GetFrozen()})
}
*result = accounts
*result = fmtAccount(balances)
return nil
}
......@@ -1209,3 +1202,14 @@ func convertBlockDetails(details []*types.BlockDetail, retDetails *rpctypes.Bloc
}
return nil
}
func fmtAccount(balances []*types.Account) []*rpctypes.Account {
var accounts []*rpctypes.Account
for _, balance := range balances {
accounts = append(accounts, &rpctypes.Account{Addr: balance.GetAddr(),
Balance: balance.GetBalance(),
Currency: balance.GetCurrency(),
Frozen: balance.GetFrozen()})
}
return accounts
}
......@@ -10,6 +10,7 @@ import (
"encoding/hex"
"github.com/33cn/chain33/account"
"github.com/33cn/chain33/client/mocks"
"github.com/33cn/chain33/common"
rpctypes "github.com/33cn/chain33/rpc/types"
......@@ -373,6 +374,7 @@ func newTestChain33(api *mocks.QueueProtocolAPI) *Chain33 {
return &Chain33{
cli: channelClient{
QueueProtocolAPI: api,
accountdb: account.NewCoinsAccount(),
},
}
}
......@@ -1290,3 +1292,58 @@ func TestChain33_GetExecBalance(t *testing.T) {
err = client.GetExecBalance(in, &testResult2)
assert.NotNil(t, err)
}
func TestChain33_GetBalance(t *testing.T) {
api := new(mocks.QueueProtocolAPI)
client := newTestChain33(api)
var addrs = []string{"1Jn2qu84Z1SUUosWjySggBS9pKWdAP3tZt"}
cases := []struct {
In types.ReqBalance
}{
{In: types.ReqBalance{
Execer: types.ExecName("coins"),
Addresses: addrs,
}},
{In: types.ReqBalance{
Execer: types.ExecName("ticket"),
Addresses: addrs,
}},
{In: types.ReqBalance{
AssetSymbol: "bty",
AssetExec: "coins",
Execer: types.ExecName("ticket"),
Addresses: addrs,
}},
{In: types.ReqBalance{
AssetSymbol: "bty",
AssetExec: "coins",
Execer: types.ExecName("coins"),
Addresses: addrs,
}},
}
for _, c := range cases {
c := c
t.Run("test GetBalance", func(t *testing.T) {
head := &types.Header{StateHash: []byte("sdfadasds")}
api.On("GetLastHeader").Return(head, nil)
var acc = &types.Account{Addr: "1Jn2qu84Z1SUUosWjySggBS9pKWdAP3tZt", Balance: 100}
accv := types.Encode(acc)
storevalue := &types.StoreReplyValue{}
storevalue.Values = append(storevalue.Values, accv)
api.On("StoreGet", mock.Anything).Return(storevalue, nil)
var data interface{}
err := client.GetBalance(c.In, &data)
assert.Nil(t, err)
result := data.([]*rpctypes.Account)
assert.Equal(t, 1, len(result))
//t.Error("result", "x", result)
assert.Equal(t, acc.Addr, result[0].Addr)
assert.Equal(t, int64(100), result[0].Balance)
})
}
}
// 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 commands
import (
"encoding/json"
"fmt"
"math"
"os"
"strings"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/rpc/jsonclient"
rpcTypes "github.com/33cn/chain33/rpc/types"
"github.com/33cn/chain33/types"
"github.com/spf13/cobra"
)
// AssetCmd command
func AssetCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "asset",
Short: "Asset query",
Args: cobra.MinimumNArgs(1),
}
cmd.AddCommand(
GetAssetBalanceCmd(),
)
return cmd
}
// GetAssetBalanceCmd query asset balance
func GetAssetBalanceCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "balance",
Short: "Query asset balance",
Run: assetBalance,
}
addAssetBalanceFlags(cmd)
return cmd
}
func addAssetBalanceFlags(cmd *cobra.Command) {
cmd.Flags().StringP("addr", "a", "", "account addr")
cmd.MarkFlagRequired("addr")
cmd.Flags().StringP("exec", "e", "", getExecuterNameString())
cmd.Flags().StringP("asset_exec", "", "coins", "the asset executor")
cmd.MarkFlagRequired("asset_exec")
cmd.Flags().StringP("asset_symbol", "", "bty", "the asset symbol")
cmd.MarkFlagRequired("asset_symbol")
cmd.Flags().IntP("height", "", -1, "block height")
}
func assetBalance(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
addr, _ := cmd.Flags().GetString("addr")
execer, _ := cmd.Flags().GetString("exec")
asset_symbol, _ := cmd.Flags().GetString("asset_symbol")
asset_exec, _ := cmd.Flags().GetString("asset_exec")
height, _ := cmd.Flags().GetInt("height")
err := address.CheckAddress(addr)
if err != nil {
if err = address.CheckMultiSignAddress(addr); err != nil {
fmt.Fprintln(os.Stderr, types.ErrInvalidAddress)
return
}
}
if execer == "" {
execer = asset_exec
}
if ok := types.IsAllowExecName([]byte(execer), []byte(execer)); !ok {
fmt.Fprintln(os.Stderr, types.ErrExecNameNotAllow)
return
}
stateHash := ""
if height >= 0 {
params := types.ReqBlocks{
Start: int64(height),
End: int64(height),
IsDetail: false,
}
var res rpcTypes.Headers
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.GetHeaders", params, &res)
_, err := ctx.RunResult()
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
h := res.Items[0]
stateHash = h.StateHash
}
var addrs []string
addrs = append(addrs, addr)
params := types.ReqBalance{
Addresses: addrs,
Execer: execer,
StateHash: stateHash,
AssetExec: asset_exec,
AssetSymbol: asset_symbol,
}
var res []*rpcTypes.Account
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.GetBalance", params, &res)
ctx.SetResultCb(parseGetBalanceRes)
ctx.Run()
}
// CreateAssetSendToExec 通用的创建 send_exec 交易, 额外指定资产合约
func CreateAssetSendToExec(cmd *cobra.Command, args []string, fromExec string) {
paraName, _ := cmd.Flags().GetString("paraName")
exec, _ := cmd.Flags().GetString("exec")
exec = getRealExecName(paraName, exec)
to, err := GetExecAddr(exec)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
amount, _ := cmd.Flags().GetFloat64("amount")
note, _ := cmd.Flags().GetString("note")
symbol, _ := cmd.Flags().GetString("symbol")
payload := &types.AssetsTransferToExec{
To: to,
Amount: int64(math.Trunc((amount+0.0000001)*1e4)) * 1e4,
Note: []byte(note),
Cointoken: symbol,
ExecName: exec,
}
data, err := json.Marshal(&payload)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
params := &rpcTypes.CreateTxIn{
Execer: types.ExecName(fromExec),
ActionName: "TransferToExec",
Payload: data,
}
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, nil)
ctx.RunWithoutMarshal()
}
// CreateAssetWithdraw 通用的创建 withdraw 交易, 额外指定资产合约
func CreateAssetWithdraw(cmd *cobra.Command, args []string, fromExec string) {
exec, _ := cmd.Flags().GetString("exec")
paraName, _ := cmd.Flags().GetString("paraName")
exec = getRealExecName(paraName, exec)
amount, _ := cmd.Flags().GetFloat64("amount")
note, _ := cmd.Flags().GetString("note")
symbol, _ := cmd.Flags().GetString("symbol")
exec = getRealExecName(paraName, exec)
execAddr, err := GetExecAddr(exec)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
payload := &types.AssetsWithdraw{
To: execAddr,
Amount: int64(math.Trunc((amount+0.0000001)*1e4)) * 1e4,
Note: []byte(note),
Cointoken: symbol,
ExecName: exec,
}
data, err := json.Marshal(&payload)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
params := &rpcTypes.CreateTxIn{
Execer: types.ExecName(fromExec),
ActionName: "Withdraw",
Payload: data,
}
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, nil)
ctx.RunWithoutMarshal()
}
// CreateAssetTransfer 通用的创建 transfer 交易, 额外指定资产合约
func CreateAssetTransfer(cmd *cobra.Command, args []string, fromExec string) {
toAddr, _ := cmd.Flags().GetString("to")
amount, _ := cmd.Flags().GetFloat64("amount")
note, _ := cmd.Flags().GetString("note")
symbol, _ := cmd.Flags().GetString("symbol")
payload := &types.AssetsTransfer{
To: toAddr,
Amount: int64(math.Trunc((amount+0.0000001)*1e4)) * 1e4,
Note: []byte(note),
Cointoken: symbol,
}
data, err := json.Marshal(&payload)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
params := &rpcTypes.CreateTxIn{
Execer: types.ExecName(fromExec),
ActionName: "Transfer",
Payload: data,
}
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, nil)
ctx.RunWithoutMarshal()
}
// GetExecAddr 获取执行器地址
func GetExecAddr(exec string) (string, error) {
if ok := types.IsAllowExecName([]byte(exec), []byte(exec)); !ok {
return "", types.ErrExecNameNotAllow
}
addrResult := address.ExecAddress(exec)
result := addrResult
return result, nil
}
func getRealExecName(paraName string, name string) string {
if strings.HasPrefix(name, "user.p.") {
return name
}
return paraName + name
}
......@@ -205,6 +205,8 @@ type ReqBalance struct {
//执行器名称
Execer string `protobuf:"bytes,2,opt,name=execer,proto3" json:"execer,omitempty"`
StateHash string `protobuf:"bytes,3,opt,name=stateHash,proto3" json:"stateHash,omitempty"`
AssetExec string `protobuf:"bytes,4,opt,name=asset_exec,json=assetExec,proto3" json:"asset_exec,omitempty"`
AssetSymbol string `protobuf:"bytes,5,opt,name=asset_symbol,json=assetSymbol,proto3" json:"asset_symbol,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
......@@ -256,6 +258,20 @@ func (m *ReqBalance) GetStateHash() string {
return ""
}
func (m *ReqBalance) GetAssetExec() string {
if m != nil {
return m.AssetExec
}
return ""
}
func (m *ReqBalance) GetAssetSymbol() string {
if m != nil {
return m.AssetSymbol
}
return ""
}
// Account 的列表
type Accounts struct {
Acc []*Account `protobuf:"bytes,1,rep,name=acc,proto3" json:"acc,omitempty"`
......@@ -403,28 +419,30 @@ func init() {
func init() { proto.RegisterFile("account.proto", fileDescriptor_8e28828dcb8d24f0) }
var fileDescriptor_8e28828dcb8d24f0 = []byte{
// 360 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x52, 0x41, 0x4f, 0x32, 0x31,
0x10, 0x4d, 0x59, 0x60, 0xd9, 0x21, 0x1f, 0x87, 0x1e, 0xc8, 0x86, 0x7c, 0xc6, 0xcd, 0x9e, 0xf6,
0x60, 0x96, 0xc4, 0xf5, 0x0f, 0x40, 0x62, 0xe2, 0xcd, 0xa4, 0xf1, 0xc4, 0xc9, 0x52, 0x06, 0x21,
0x62, 0x77, 0x6d, 0x8b, 0x11, 0x7f, 0x80, 0xbf, 0xdb, 0xb4, 0x74, 0x61, 0x91, 0x68, 0xbc, 0xf5,
0xcd, 0xeb, 0xbc, 0xf7, 0x66, 0x5a, 0xf8, 0xc7, 0x85, 0x28, 0xb7, 0xd2, 0xe4, 0x95, 0x2a, 0x4d,
0x49, 0x3b, 0x66, 0x57, 0xa1, 0x4e, 0x9f, 0x21, 0x9c, 0xec, 0xeb, 0x74, 0x04, 0x3d, 0xb1, 0x55,
0x0a, 0xa5, 0xd8, 0xc5, 0x24, 0x21, 0x59, 0x87, 0x1d, 0x30, 0x8d, 0x21, 0x9c, 0xf3, 0x0d, 0x97,
0x02, 0xe3, 0x56, 0x42, 0xb2, 0x80, 0xd5, 0x90, 0x0e, 0xa1, 0xbb, 0x54, 0xe5, 0x07, 0xca, 0x38,
0x70, 0x84, 0x47, 0x94, 0x42, 0x9b, 0x2f, 0x16, 0x2a, 0x6e, 0x27, 0x24, 0x8b, 0x98, 0x3b, 0xa7,
0x9f, 0x04, 0x46, 0x0c, 0x05, 0xae, 0x2b, 0x73, 0xfb, 0x8e, 0xc2, 0x1b, 0x3f, 0x28, 0x2e, 0xf5,
0x12, 0x95, 0x0d, 0x80, 0xb6, 0x6c, 0xdb, 0x88, 0x6b, 0x3b, 0x60, 0x9a, 0x42, 0xbb, 0x52, 0xf8,
0xe6, 0xdc, 0xfb, 0xd7, 0x83, 0xdc, 0xa5, 0xcf, 0xbd, 0x02, 0x73, 0x1c, 0xcd, 0x20, 0xdc, 0x07,
0x36, 0x2e, 0xcb, 0xf9, 0xb5, 0x9a, 0x4e, 0x97, 0x30, 0xf4, 0x39, 0xbe, 0x67, 0xa8, 0x7d, 0xc8,
0xdf, 0x7c, 0x5a, 0xbf, 0xfb, 0x3c, 0x02, 0x30, 0x7c, 0x9d, 0xfa, 0x55, 0xfd, 0x87, 0xc8, 0xae,
0x01, 0xb5, 0x46, 0x1d, 0x93, 0x24, 0xc8, 0x22, 0x76, 0x2c, 0xd8, 0x45, 0xda, 0x69, 0x51, 0x39,
0xd1, 0x88, 0x79, 0x64, 0xbb, 0xb4, 0xe1, 0x06, 0xef, 0xb8, 0x5e, 0xb9, 0xb9, 0x22, 0x76, 0x2c,
0xa4, 0x57, 0xd0, 0xf3, 0xae, 0x9a, 0x26, 0x10, 0x70, 0x21, 0x9c, 0xf2, 0x79, 0x26, 0x4b, 0xa5,
0xf7, 0xd0, 0x6f, 0x2c, 0xbe, 0x61, 0x49, 0x4e, 0x2c, 0x33, 0x08, 0xfd, 0x67, 0xf9, 0x69, 0x40,
0x4f, 0xa7, 0x33, 0x18, 0x4c, 0x36, 0x1b, 0xab, 0x59, 0x0f, 0x59, 0xbf, 0x3b, 0x39, 0xbe, 0x3b,
0xbd, 0x39, 0xb1, 0x8d, 0x5b, 0x2e, 0x20, 0xf5, 0x9a, 0x0d, 0x86, 0x35, 0xaf, 0x4d, 0x2f, 0x67,
0x17, 0x4f, 0x6b, 0xb3, 0xda, 0xce, 0x73, 0x51, 0xbe, 0x8c, 0x8b, 0x42, 0xc8, 0xb1, 0x58, 0xf1,
0xb5, 0x2c, 0x8a, 0xb1, 0xeb, 0x9c, 0x77, 0xdd, 0x4f, 0x2e, 0xbe, 0x02, 0x00, 0x00, 0xff, 0xff,
0x7b, 0xae, 0x1c, 0x1e, 0xda, 0x02, 0x00, 0x00,
// 399 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0xc1, 0x8e, 0xd3, 0x30,
0x10, 0x95, 0x9b, 0x76, 0xb3, 0x99, 0xc2, 0x1e, 0x7c, 0x58, 0x59, 0x2b, 0x56, 0x84, 0x9c, 0x72,
0x40, 0xa9, 0x44, 0xf8, 0x81, 0x56, 0x42, 0xe2, 0x86, 0x64, 0x38, 0xf5, 0x82, 0x1c, 0x77, 0x4a,
0x2b, 0xd2, 0x24, 0xd8, 0x2e, 0xa2, 0x7c, 0x00, 0x1f, 0xc2, 0x97, 0x22, 0x4f, 0x9d, 0x36, 0xa5,
0x02, 0xed, 0xad, 0xf3, 0xde, 0xcc, 0xbc, 0xe7, 0xd7, 0x09, 0x3c, 0x57, 0x5a, 0xb7, 0xfb, 0xc6,
0x15, 0x9d, 0x69, 0x5d, 0xcb, 0x27, 0xee, 0xd0, 0xa1, 0xcd, 0xbe, 0x42, 0x3c, 0x3f, 0xe2, 0xfc,
0x01, 0x6e, 0xf5, 0xde, 0x18, 0x6c, 0xf4, 0x41, 0xb0, 0x94, 0xe5, 0x13, 0x79, 0xaa, 0xb9, 0x80,
0xb8, 0x52, 0xb5, 0x6a, 0x34, 0x8a, 0x51, 0xca, 0xf2, 0x48, 0xf6, 0x25, 0xbf, 0x87, 0x9b, 0xb5,
0x69, 0x7f, 0x62, 0x23, 0x22, 0x22, 0x42, 0xc5, 0x39, 0x8c, 0xd5, 0x6a, 0x65, 0xc4, 0x38, 0x65,
0x79, 0x22, 0xe9, 0x77, 0xf6, 0x8b, 0xc1, 0x83, 0x44, 0x8d, 0xdb, 0xce, 0xbd, 0xfb, 0x81, 0x3a,
0x08, 0x7f, 0x32, 0xaa, 0xb1, 0x6b, 0x34, 0xde, 0x00, 0x7a, 0xd8, 0x8f, 0x31, 0x1a, 0x3b, 0xd5,
0x3c, 0x83, 0x71, 0x67, 0xf0, 0x3b, 0xa9, 0x4f, 0xdf, 0xdc, 0x15, 0xe4, 0xbe, 0x08, 0x1b, 0x24,
0x71, 0x3c, 0x87, 0xf8, 0x68, 0xd8, 0x91, 0x97, 0xeb, 0xb6, 0x9e, 0xce, 0xd6, 0x70, 0x1f, 0x7c,
0xfc, 0xed, 0xa1, 0xd7, 0x61, 0x4f, 0xd3, 0x19, 0xfd, 0x5f, 0xe7, 0x37, 0x03, 0x90, 0xf8, 0x6d,
0x11, 0xb2, 0x7a, 0x01, 0x89, 0xcf, 0x01, 0xad, 0x45, 0x2b, 0x58, 0x1a, 0xe5, 0x89, 0x3c, 0x03,
0x3e, 0x49, 0xff, 0x5c, 0x34, 0xb4, 0x35, 0x91, 0xa1, 0xf2, 0x53, 0xd6, 0x29, 0x87, 0xef, 0x95,
0xdd, 0xd0, 0xc3, 0x12, 0x79, 0x06, 0xf8, 0x23, 0x80, 0xb2, 0x16, 0xdd, 0x67, 0xdf, 0x1d, 0xd2,
0x4e, 0x08, 0xf1, 0x11, 0xf3, 0x57, 0xf0, 0xec, 0x48, 0xdb, 0xc3, 0xae, 0x6a, 0x6b, 0x31, 0xa1,
0x86, 0x29, 0x61, 0x1f, 0x09, 0xca, 0x5e, 0xc3, 0x6d, 0x30, 0x6e, 0x79, 0x0a, 0x91, 0xd2, 0x9a,
0xbc, 0x5d, 0x3f, 0xcb, 0x53, 0xd9, 0x07, 0x98, 0x0e, 0xfe, 0xbb, 0x81, 0x69, 0x76, 0x61, 0x3a,
0x87, 0x38, 0xdc, 0xdb, 0xbf, 0x32, 0x0a, 0x74, 0xb6, 0x84, 0xbb, 0x79, 0x5d, 0xfb, 0x9d, 0x7d,
0x4c, 0xfd, 0xe9, 0xb0, 0xf3, 0xe9, 0xf0, 0xb7, 0x17, 0xb2, 0x62, 0x44, 0x06, 0x79, 0xd8, 0x39,
0x60, 0xe4, 0xb0, 0x6d, 0xf1, 0x72, 0xf9, 0xf8, 0x65, 0xeb, 0x36, 0xfb, 0xaa, 0xd0, 0xed, 0x6e,
0x56, 0x96, 0xba, 0x99, 0xe9, 0x8d, 0xda, 0x36, 0x65, 0x39, 0xa3, 0xc9, 0xea, 0x86, 0x3e, 0x86,
0xf2, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb3, 0x61, 0x7c, 0x60, 0x1d, 0x03, 0x00, 0x00,
}
......@@ -38,8 +38,10 @@ message ReqBalance {
//地址列表
repeated string addresses = 1;
//执行器名称
string execer = 2;
string stateHash = 3;
string execer = 2;
string stateHash = 3;
string asset_exec = 4;
string asset_symbol = 5;
}
// Account 的列表
......
......@@ -60,6 +60,7 @@ func init() {
commands.VersionCmd(),
sendCmd,
closeCmd,
commands.AssetCmd(),
)
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment