Commit 2d0bd9cc authored by heyubin's avatar heyubin

Merge branch 'master' into multisig

parents 711b2b26 4914e587
// 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 executor
import (
"bytes"
"errors"
"fmt"
"math/rand"
"testing"
"github.com/33cn/chain33/client"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/executor"
"github.com/33cn/chain33/queue"
drivers "github.com/33cn/chain33/system/dapp"
pty "github.com/33cn/chain33/system/dapp/manage/types"
"github.com/33cn/chain33/types"
rt "github.com/33cn/plugin/plugin/dapp/lottery/types"
)
var (
creatorAddr string
buyAddr string
buyPriv crypto.PrivKey
creatorPriv crypto.PrivKey
testNormErr error
lottery drivers.Driver
r *rand.Rand
mydb db.KV
lotteryID string
)
func init() {
creatorAddr, creatorPriv = genaddress()
buyAddr, buyPriv = genaddress()
testNormErr = errors.New("Err")
lottery = constructLotteryInstance()
r = rand.New(rand.NewSource(types.Now().UnixNano()))
}
func TestExecCreateLottery(t *testing.T) {
var targetReceipt types.Receipt
var targetErr = rt.ErrNoPrivilege
var receipt *types.Receipt
var err error
targetReceipt.Ty = 2
tx := ConstructCreateTx()
receipt, err = lottery.Exec(tx, 0)
// ErrNoPrivilege case
if !CompareLotteryExecResult(receipt, err, &targetReceipt, targetErr) {
t.Error(testNormErr)
}
var item types.ConfigItem
item.Key = "lottery-creator"
item.Addr = creatorAddr
item.Ty = pty.ConfigItemArrayConfig
emptyValue := &types.ArrayConfig{Value: make([]string, 0)}
arr := types.ConfigItem_Arr{Arr: emptyValue}
item.Value = &arr
item.GetArr().Value = append(item.GetArr().Value, creatorAddr)
item.Addr = creatorAddr
key := types.ManageKey("lottery-creator")
valueSave := types.Encode(&item)
mydb.Set([]byte(key), valueSave)
// success case
targetErr = nil
receipt, err = lottery.Exec(tx, 0)
if !CompareLotteryExecResult(receipt, err, &targetReceipt, targetErr) {
t.Error(testNormErr)
}
lotteryID = common.ToHex(tx.Hash())
fmt.Println(lotteryID)
}
func TestExecBuyLottery(t *testing.T) {
var targetReceipt types.Receipt
var targetErr = types.ErrNoBalance
var receipt *types.Receipt
var err error
targetReceipt.Ty = 2
tx := ConstructBuyTx()
receipt, err = lottery.Exec(tx, 0)
// ErrNoBalance case
if !CompareLotteryExecResult(receipt, err, &targetReceipt, targetErr) {
t.Error(testNormErr)
}
acc1 := lottery.GetCoinsAccount().LoadExecAccount(buyAddr, address.ExecAddress("lottery"))
acc1.Balance = 10000000000
lottery.GetCoinsAccount().SaveExecAccount(address.ExecAddress("lottery"), acc1)
targetErr = nil
receipt, err = lottery.Exec(tx, 0)
// success case
if !CompareLotteryExecResult(receipt, err, &targetReceipt, targetErr) {
t.Error(testNormErr)
}
}
func TestExecDrawLottery(t *testing.T) {
var targetReceipt types.Receipt
var targetErr = rt.ErrLotteryStatus
var receipt *types.Receipt
var err error
targetReceipt.Ty = 2
tx := ConstructDrawTx()
receipt, err = lottery.Exec(tx, 0)
// ErrLotteryStatus case
if !CompareLotteryExecResult(receipt, err, &targetReceipt, targetErr) {
t.Error(testNormErr)
}
lottery.SetEnv(100, 0, 0)
receipt, err = lottery.Exec(tx, 0)
targetErr = types.ErrActionNotSupport
// ErrActionNotSupport case
if !CompareLotteryExecResult(receipt, err, &targetReceipt, targetErr) {
t.Error(testNormErr)
}
// mock message between randnum nextstep
}
func genaddress() (string, crypto.PrivKey) {
cr, err := crypto.New(types.GetSignName("", types.SECP256K1))
if err != nil {
panic(err)
}
privto, err := cr.GenKey()
if err != nil {
panic(err)
}
addrto := address.PubKeyToAddress(privto.PubKey().Bytes())
return addrto.String(), privto
}
func NewTestDB() db.KV {
return executor.NewStateDB(nil, nil, nil, &executor.StateDBOption{Height: types.GetFork("ForkExecRollback")})
}
func ConstructCreateTx() *types.Transaction {
var purBlockNum int64 = 30
var drawBlockNum int64 = 40
var opRatio int64 = 10
var devRatio int64 = 10
var fee int64 = 1e6
vcreate := &rt.LotteryAction_Create{Create: &rt.LotteryCreate{PurBlockNum: purBlockNum, DrawBlockNum: drawBlockNum, OpRewardRatio: opRatio, DevRewardRatio: devRatio}}
transfer := &rt.LotteryAction{Value: vcreate, Ty: rt.LotteryActionCreate}
tx := &types.Transaction{Execer: []byte("lottery"), Payload: types.Encode(transfer), Fee: fee, To: address.ExecAddress(types.ExecName(rt.LotteryX))}
tx.Nonce = r.Int63()
tx.Sign(types.SECP256K1, creatorPriv)
return tx
}
func ConstructBuyTx() *types.Transaction {
var amount int64 = 1
var number int64 = 12345
var way int64 = 1
var fee int64 = 1e6
vbuy := &rt.LotteryAction_Buy{Buy: &rt.LotteryBuy{LotteryId: lotteryID, Amount: amount, Number: number, Way: way}}
transfer := &rt.LotteryAction{Value: vbuy, Ty: rt.LotteryActionBuy}
tx := &types.Transaction{Execer: []byte("lottery"), Payload: types.Encode(transfer), Fee: fee, To: address.ExecAddress(types.ExecName(rt.LotteryX))}
tx.Nonce = r.Int63()
tx.Sign(types.SECP256K1, buyPriv)
return tx
}
func ConstructDrawTx() *types.Transaction {
var fee int64 = 1e6
vdraw := &rt.LotteryAction_Draw{Draw: &rt.LotteryDraw{LotteryId: lotteryID}}
transfer := &rt.LotteryAction{Value: vdraw, Ty: rt.LotteryActionDraw}
tx := &types.Transaction{Execer: []byte("lottery"), Payload: types.Encode(transfer), Fee: fee, To: address.ExecAddress(types.ExecName(rt.LotteryX))}
tx.Nonce = r.Int63()
tx.Sign(types.SECP256K1, creatorPriv)
return tx
}
func constructLotteryInstance() drivers.Driver {
lottery := newLottery()
//lottery.SetStateDB(NewTestDB())
mydb = NewTestDB()
lottery.SetStateDB(mydb)
lottery.SetLocalDB(NewTestLDB())
q := queue.New("channel")
client.New(q.Client(), nil)
//lottery.SetAPI(qclient)
return lottery
}
func CompareLotteryExecLocalRes(dbset1 *types.LocalDBSet, err1 error, dbset2 *types.LocalDBSet, err2 error) bool {
//fmt.Println(err1, err2, dbset1, dbset2)
if err1 != err2 {
fmt.Println(err1, err2)
return false
}
if dbset1 == nil && dbset2 == nil {
return true
}
if (dbset1 == nil) != (dbset2 == nil) {
return false
}
if dbset1.KV == nil && dbset2.KV == nil {
return true
}
if (dbset1.KV == nil) != (dbset2.KV == nil) {
return false
}
if len(dbset1.KV) != len(dbset2.KV) {
return false
}
for i := range dbset1.KV {
if !bytes.Equal(dbset1.KV[i].Key, dbset2.KV[i].Key) {
return false
}
if !bytes.Equal(dbset1.KV[i].Value, dbset2.KV[i].Value) {
return false
}
}
return true
}
func CompareLotteryExecResult(rec1 *types.Receipt, err1 error, rec2 *types.Receipt, err2 error) bool {
//fmt.Println(err1, err2, rec1, rec2)
if err1 != err2 {
fmt.Println(err1, err2)
return false
}
// err, so receipt not concerned
if err1 != nil && err1 == err2 {
return true
}
if (rec1 == nil) != (rec2 == nil) {
return false
}
if rec1.Ty != rec2.Ty {
fmt.Println(rec1.Ty, rec2.Ty)
return false
}
return true
}
type TestLDB struct {
db.TransactionDB
cache map[string][]byte
}
func NewTestLDB() *TestLDB {
return &TestLDB{cache: make(map[string][]byte)}
}
func (e *TestLDB) Get(key []byte) (value []byte, err error) {
if value, ok := e.cache[string(key)]; ok {
//elog.Error("getkey", "key", string(key), "value", string(value))
return value, nil
}
return nil, types.ErrNotFound
}
func (e *TestLDB) Set(key []byte, value []byte) error {
//elog.Error("setkey", "key", string(key), "value", string(value))
e.cache[string(key)] = value
return nil
}
func (e *TestLDB) BatchGet(keys [][]byte) (values [][]byte, err error) {
return nil, types.ErrNotFound
}
//从数据库中查询数据列表,set 中的cache 更新不会影响这个list
func (e *TestLDB) List(prefix, key []byte, count, direction int32) ([][]byte, error) {
return nil, types.ErrNotFound
}
func (e *TestLDB) PrefixCount(prefix []byte) int64 {
return 0
}
......@@ -9,59 +9,10 @@ import (
"time"
"github.com/33cn/chain33/types"
pty "github.com/33cn/plugin/plugin/dapp/lottery/types"
tickettypes "github.com/33cn/plugin/plugin/dapp/ticket/types"
)
const retryNum = 10
//different impl on main chain and parachain
func (action *Action) getTxActions(height int64, blockNum int64) ([]*tickettypes.TicketAction, error) {
var txActions []*tickettypes.TicketAction
llog.Error("getTxActions", "height", height, "blockNum", blockNum)
if !types.IsPara() {
req := &types.ReqBlocks{Start: height - blockNum + 1, End: height, IsDetail: false, Pid: []string{""}}
blockDetails, err := action.api.GetBlocks(req)
if err != nil {
llog.Error("getTxActions", "height", height, "blockNum", blockNum, "err", err)
return txActions, err
}
for _, block := range blockDetails.Items {
llog.Debug("getTxActions", "blockHeight", block.Block.Height, "blockhash", block.Block.Hash())
ticketAction, err := action.getMinerTx(block.Block)
if err != nil {
return txActions, err
}
txActions = append(txActions, ticketAction)
}
return txActions, nil
}
//block height on main
mainHeight := action.GetMainHeightByTxHash(action.txhash)
if mainHeight < 0 {
llog.Error("LotteryCreate", "mainHeight", mainHeight)
return nil, pty.ErrLotteryStatus
}
blockDetails, err := action.GetBlocksOnMain(mainHeight-blockNum, mainHeight-1)
if err != nil {
llog.Error("LotteryCreate", "mainHeight", mainHeight)
return nil, pty.ErrLotteryStatus
}
for _, block := range blockDetails.Items {
ticketAction, err := action.getMinerTx(block.Block)
if err != nil {
return txActions, err
}
txActions = append(txActions, ticketAction)
}
return txActions, nil
}
// GetMainHeightByTxHash get Block height
func (action *Action) GetMainHeightByTxHash(txHash []byte) int64 {
for i := 0; i < retryNum; i++ {
......@@ -76,58 +27,3 @@ func (action *Action) GetMainHeightByTxHash(txHash []byte) int64 {
return -1
}
// GetBlocksOnMain get Block from main chain
func (action *Action) GetBlocksOnMain(start int64, end int64) (*types.BlockDetails, error) {
req := &types.ReqBlocks{Start: start, End: end, IsDetail: false, Pid: []string{""}}
getBlockSucc := false
var reply *types.Reply
var err error
for i := 0; i < retryNum; i++ {
reply, err = action.grpcClient.GetBlocks(context.Background(), req)
if err != nil {
llog.Error("GetBlocksOnMain", "start", start, "end", end, "err", err)
time.Sleep(time.Second)
} else {
getBlockSucc = true
break
}
}
if !getBlockSucc {
return nil, err
}
var blockDetails types.BlockDetails
err = types.Decode(reply.Msg, &blockDetails)
if err != nil {
llog.Error("GetBlocksOnMain", "err", err)
return nil, err
}
return &blockDetails, nil
}
func (action *Action) getMinerTx(current *types.Block) (*tickettypes.TicketAction, error) {
//检查第一个笔交易的execs, 以及执行状态
if len(current.Txs) == 0 {
return nil, types.ErrEmptyTx
}
baseTx := current.Txs[0]
//判断交易类型和执行情况
var ticketAction tickettypes.TicketAction
err := types.Decode(baseTx.GetPayload(), &ticketAction)
if err != nil {
return nil, err
}
if ticketAction.GetTy() != tickettypes.TicketActionMiner {
return nil, types.ErrCoinBaseTxType
}
//判断交易执行是否OK
if ticketAction.GetMiner() == nil {
return nil, tickettypes.ErrEmptyMinerTx
}
return &ticketAction, nil
}
......@@ -5,8 +5,7 @@
package executor
import (
"fmt"
"sort"
"context"
"strconv"
"github.com/33cn/chain33/account"
......@@ -20,10 +19,10 @@ import (
)
const (
exciting = 100000 / 2
lucky = 1000 / 2
happy = 100 / 2
notbad = 10 / 2
exciting = 100000
lucky = 1000
happy = 100
notbad = 10
)
const (
......@@ -51,13 +50,22 @@ const (
OneStar = 1
)
const luckyNumMol = 100000
const decimal = 100000000 //1e8
const randMolNum = 5
const grpcRecSize int = 5 * 30 * 1024 * 1024
const blockNum = 5
const (
luckyNumMol = 100000
decimal = 100000000 //1e8
//randMolNum = 5
grpcRecSize int = 5 * 30 * 1024 * 1024
blockNum = 5
)
const (
maxRatio = 100
rewardBase = 1000
devRewardAddr = "1D6RFZNp2rh6QdbcZ1d7RWuBUz61We6SD7"
opRewardAddr = "1PHtChNt3UcfssR7v7trKSk3WJtAWjKjjX"
)
// LotteryDB struct
// LotteryDB def
type LotteryDB struct {
pty.Lottery
}
......@@ -127,6 +135,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)
if err != nil {
......@@ -187,6 +198,9 @@ func (action *Action) LotteryCreate(create *pty.LotteryCreate) (*types.Receipt,
lotteryID := common.ToHex(action.txhash)
if create.OpRewardRatio > maxRatio || create.DevRewardRatio > maxRatio || create.OpRewardRatio < 0 || create.DevRewardRatio < 0 {
return nil, pty.ErrRewardFactor
}
if !isRightCreator(action.fromaddr, action.db, false) {
return nil, pty.ErrNoPrivilege
}
......@@ -212,6 +226,9 @@ func (action *Action) LotteryCreate(create *pty.LotteryCreate) (*types.Receipt,
lott := NewLotteryDB(lotteryID, create.GetPurBlockNum(),
create.GetDrawBlockNum(), action.height, action.fromaddr)
lott.OpRewardRatio = create.OpRewardRatio
lott.DevRewardRatio = create.DevRewardRatio
llog.Debug("LotteryCreate", "OpRewardRatio", lott.OpRewardRatio, "DevRewardRatio", lott.DevRewardRatio)
if types.IsPara() {
mainHeight := action.GetMainHeightByTxHash(action.txhash)
if mainHeight < 0 {
......@@ -310,11 +327,6 @@ func (action *Action) LotteryBuy(buy *pty.LotteryBuy) (*types.Receipt, error) {
return nil, pty.ErrLotteryBuyNumber
}
if lott.Records == nil {
llog.Debug("LotteryBuy records init")
lott.Records = make(map[string]*pty.PurchaseRecords)
}
newRecord := &pty.PurchaseRecord{Amount: buy.GetAmount(), Number: buy.GetNumber(), Index: action.GetIndex(), Way: buy.GetWay()}
llog.Debug("LotteryBuy", "amount", buy.GetAmount(), "number", buy.GetNumber())
......@@ -340,18 +352,25 @@ func (action *Action) LotteryBuy(buy *pty.LotteryBuy) (*types.Receipt, error) {
kv = append(kv, receipt.KV...)
lott.Fund += buy.GetAmount()
lott.TotalPurchasedTxNum++
if record, ok := lott.Records[action.fromaddr]; ok {
record.Record = append(record.Record, newRecord)
} else {
newAddr := true
for i := range lott.PurRecords {
if action.fromaddr == lott.PurRecords[i].Addr {
lott.PurRecords[i].Record = append(lott.PurRecords[i].Record, newRecord)
lott.PurRecords[i].AmountOneRound += buy.Amount
newAddr = false
break
}
}
if newAddr {
initrecord := &pty.PurchaseRecords{}
initrecord.Record = append(initrecord.Record, newRecord)
initrecord.FundWin = 0
initrecord.AmountOneRound = 0
lott.Records[action.fromaddr] = initrecord
initrecord.AmountOneRound = buy.Amount
initrecord.Addr = action.fromaddr
lott.PurRecords = append(lott.PurRecords, initrecord)
}
lott.Records[action.fromaddr].AmountOneRound += buy.Amount
lott.TotalPurchasedTxNum++
lott.Save(action.db)
kv = append(kv, lott.GetKVSet()...)
......@@ -364,8 +383,6 @@ func (action *Action) LotteryBuy(buy *pty.LotteryBuy) (*types.Receipt, error) {
}
// LotteryDraw Action
// 1.Anyone who buy a ticket
// 2.Creator
func (action *Action) LotteryDraw(draw *pty.LotteryDraw) (*types.Receipt, error) {
var logs []*types.ReceiptLog
var kv []*types.KeyValue
......@@ -404,10 +421,10 @@ func (action *Action) LotteryDraw(draw *pty.LotteryDraw) (*types.Receipt, error)
}
if action.fromaddr != lott.GetCreateAddr() {
if _, ok := lott.Records[action.fromaddr]; !ok {
llog.Error("LotteryDraw", "action.fromaddr", action.fromaddr)
return nil, pty.ErrLotteryDrawActionInvalid
}
//if _, ok := lott.Records[action.fromaddr]; !ok {
llog.Error("LotteryDraw", "action.fromaddr", action.fromaddr)
return nil, pty.ErrLotteryDrawActionInvalid
//}
}
rec, updateInfo, err := action.checkDraw(lott)
......@@ -454,13 +471,9 @@ func (action *Action) LotteryClose(draw *pty.LotteryClose) (*types.Receipt, erro
return nil, pty.ErrLotteryStatus
}
addrkeys := make([]string, len(lott.Records))
i := 0
var totalReturn int64
for addr := range lott.Records {
totalReturn += lott.Records[addr].AmountOneRound
addrkeys[i] = addr
i++
for _, recs := range lott.PurRecords {
totalReturn += recs.AmountOneRound
}
llog.Debug("LotteryClose", "totalReturn", totalReturn)
......@@ -470,12 +483,10 @@ func (action *Action) LotteryClose(draw *pty.LotteryClose) (*types.Receipt, erro
return nil, pty.ErrLotteryFundNotEnough
}
sort.Strings(addrkeys)
for _, addr := range addrkeys {
if lott.Records[addr].AmountOneRound > 0 {
receipt, err := action.coinsAccount.ExecTransferFrozen(lott.CreateAddr, addr, action.execaddr,
decimal*lott.Records[addr].AmountOneRound)
for _, recs := range lott.PurRecords {
if recs.AmountOneRound > 0 {
receipt, err := action.coinsAccount.ExecTransferFrozen(lott.CreateAddr, recs.Addr, action.execaddr,
decimal*recs.AmountOneRound)
if err != nil {
return nil, err
}
......@@ -486,11 +497,10 @@ func (action *Action) LotteryClose(draw *pty.LotteryClose) (*types.Receipt, erro
}
}
for addr := range lott.Records {
lott.Records[addr].Record = lott.Records[addr].Record[0:0]
delete(lott.Records, addr)
for i := range lott.PurRecords {
lott.PurRecords[i].Record = lott.PurRecords[i].Record[0:0]
}
lott.PurRecords = lott.PurRecords[0:0]
lott.TotalPurchasedTxNum = 0
llog.Debug("LotteryClose switch to closestate")
lott.Status = pty.LotteryClosed
......@@ -504,66 +514,43 @@ func (action *Action) LotteryClose(draw *pty.LotteryClose) (*types.Receipt, erro
return &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}, nil
}
// GetCalculableHash return hash for calculation
func (action *Action) GetCalculableHash(beg, end int64, randMolNum int64) ([]byte, error) {
//通过某个区间计算modify
timeSource := int64(0)
total := int64(0)
//last := []byte("last")
for i := beg; i < end; i += randMolNum {
req := &types.ReqBlocks{Start: i, End: i, IsDetail: false, Pid: []string{""}}
blocks, err := action.api.GetBlocks(req)
if err != nil {
return []byte{}, err
}
block := blocks.Items[0].Block
timeSource += block.BlockTime
total += block.BlockTime
}
//for main chain, 5 latest block
//for para chain, 5 latest block -- 5 sequence main block
txActions, err := action.getTxActions(end, blockNum)
if err != nil {
return nil, err
}
//modify, bits, id
var modifies []byte
var bits uint32
var ticketIds string
for _, ticketAction := range txActions {
llog.Debug("GetModify", "modify", ticketAction.GetMiner().GetModify(), "bits", ticketAction.GetMiner().GetBits(), "ticketId", ticketAction.GetMiner().GetTicketId())
modifies = append(modifies, ticketAction.GetMiner().GetModify()...)
bits += ticketAction.GetMiner().GetBits()
ticketIds += ticketAction.GetMiner().GetTicketId()
}
newmodify := fmt.Sprintf("%s:%s:%d:%d", string(modifies), ticketIds, total, bits)
modify := common.Sha256([]byte(newmodify))
return modify, nil
}
//random used for verification in solo
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
num = 12345
} else {
randMolNum := (lott.TotalPurchasedTxNum+action.height-lott.LastTransToPurState)%3 + 2 //3~5
modify, err := action.GetCalculableHash(lott.LastTransToPurState, action.height-1, randMolNum)
llog.Error("findLuckyNum", "begin", lott.LastTransToPurState, "end", action.height-1, "randMolNum", randMolNum)
if err != nil {
llog.Error("findLuckyNum", "err", err)
return -1
//发消息给randnum模块
//在主链上,当前高度查询不到,如果要保证区块个数,高度传入action.height-1
llog.Debug("findLuckyNum on randnum module")
if !types.IsPara() {
req := &types.ReqRandHash{ExecName: "ticket", Height: action.height - 1, BlockNum: blockNum}
msg, err = action.api.Query("ticket", "RandNumHash", req)
if err != nil {
return -1
}
reply := msg.(*types.ReplyHash)
hash = reply.Hash
} else {
mainHeight := action.GetMainHeightByTxHash(action.txhash)
if mainHeight < 0 {
llog.Error("findLuckyNum", "mainHeight", mainHeight)
return -1
}
req := &types.ReqRandHash{ExecName: "ticket", Height: mainHeight, BlockNum: blockNum}
reply, err := action.grpcClient.QueryRandNum(context.Background(), req)
if err != nil {
return -1
}
hash = reply.Hash
}
baseNum, err := strconv.ParseUint(common.ToHex(modify[0:4]), 0, 64)
baseNum, err := strconv.ParseUint(common.ToHex(hash[0:4]), 0, 64)
llog.Debug("findLuckyNum", "baseNum", baseNum)
if err != nil {
llog.Error("findLuckyNum", "err", err)
return -1
......@@ -589,91 +576,101 @@ func checkFundAmount(luckynum int64, guessnum int64, way int64) (int64, int64) {
}
func (action *Action) checkDraw(lott *LotteryDB) (*types.Receipt, *pty.LotteryUpdateBuyInfo, error) {
llog.Debug("checkDraw")
luckynum := action.findLuckyNum(false, lott)
if luckynum < 0 || luckynum >= luckyNumMol {
return nil, nil, pty.ErrLotteryErrLuckyNum
}
llog.Error("checkDraw", "luckynum", luckynum)
llog.Debug("checkDraw", "luckynum", luckynum)
//var receipt *types.Receipt
var logs []*types.ReceiptLog
var kv []*types.KeyValue
//calculate fund for all participant showed their number
var updateInfo pty.LotteryUpdateBuyInfo
updateInfo.BuyInfo = make(map[string]*pty.LotteryUpdateRecs)
var tempFund int64
var totalFund int64
addrkeys := make([]string, len(lott.Records))
i := 0
for addr := range lott.Records {
addrkeys[i] = addr
i++
for _, rec := range lott.Records[addr].Record {
updateInfo.BuyInfo = make(map[string]*pty.LotteryUpdateRecs)
for i := range lott.PurRecords {
for _, rec := range lott.PurRecords[i].Record {
fund, fundType := checkFundAmount(luckynum, rec.Number, rec.Way)
if fund != 0 {
newUpdateRec := &pty.LotteryUpdateRec{Index: rec.Index, Type: fundType}
if update, ok := updateInfo.BuyInfo[addr]; ok {
if update, ok := updateInfo.BuyInfo[lott.PurRecords[i].Addr]; ok {
update.Records = append(update.Records, newUpdateRec)
} else {
initrecord := &pty.LotteryUpdateRecs{}
initrecord.Records = append(initrecord.Records, newUpdateRec)
updateInfo.BuyInfo[addr] = initrecord
updateInfo.BuyInfo[lott.PurRecords[i].Addr] = initrecord
}
}
tempFund = fund * rec.Amount
lott.Records[addr].FundWin += tempFund
lott.PurRecords[i].FundWin += tempFund
totalFund += tempFund
}
}
llog.Debug("checkDraw", "lenofupdate", len(updateInfo.BuyInfo))
llog.Debug("checkDraw", "update", updateInfo.BuyInfo)
llog.Debug("checkDraw", "lenofupdate", len(updateInfo.BuyInfo), "update", updateInfo.BuyInfo)
var factor float64
if totalFund > lott.GetFund()/2 {
llog.Debug("checkDraw ajust fund", "lott.Fund", lott.Fund, "totalFund", totalFund)
factor = (float64)(lott.GetFund()) / 2 / (float64)(totalFund)
lott.Fund = lott.Fund / 2
} else {
factor = 1.0
lott.Fund -= totalFund
}
if totalFund > 0 {
if totalFund > lott.GetFund()/2 {
llog.Debug("checkDraw ajust fund", "lott.Fund", lott.Fund, "totalFund", totalFund)
factor = (float64)(lott.GetFund()) / 2 / (float64)(totalFund)
lott.Fund = lott.Fund / 2
} else {
factor = 1.0
lott.Fund -= totalFund
}
llog.Debug("checkDraw", "factor", factor, "totalFund", totalFund)
llog.Debug("checkDraw", "factor", factor, "totalFund", totalFund)
//protection for rollback
if factor == 1.0 {
if !action.CheckExecAccount(lott.CreateAddr, totalFund, true) {
return nil, nil, pty.ErrLotteryFundNotEnough
}
} else {
if !action.CheckExecAccount(lott.CreateAddr, decimal*lott.Fund/2+1, true) {
return nil, nil, pty.ErrLotteryFundNotEnough
//protection for rollback
if factor == 1.0 {
if !action.CheckExecAccount(lott.CreateAddr, totalFund, true) {
return nil, nil, pty.ErrLotteryFundNotEnough
}
} else {
if !action.CheckExecAccount(lott.CreateAddr, decimal*lott.Fund/2+1, true) {
return nil, nil, pty.ErrLotteryFundNotEnough
}
}
}
sort.Strings(addrkeys)
for _, recs := range lott.PurRecords {
if recs.FundWin > 0 {
fund := (recs.FundWin * int64(factor*exciting)) * decimal * (rewardBase - lott.OpRewardRatio - lott.DevRewardRatio) / (exciting * rewardBase) //any problem when too little?
llog.Debug("checkDraw", "fund", fund)
for _, addr := range addrkeys {
fund := (lott.Records[addr].FundWin * int64(factor*exciting)) * decimal / exciting //any problem when too little?
llog.Debug("checkDraw", "fund", fund)
if fund > 0 {
receipt, err := action.coinsAccount.ExecTransferFrozen(lott.CreateAddr, addr, action.execaddr, fund)
if err != nil {
return nil, nil, err
receipt, err := action.coinsAccount.ExecTransferFrozen(lott.CreateAddr, recs.Addr, action.execaddr, fund)
if err != nil {
return nil, nil, err
}
kv = append(kv, receipt.KV...)
logs = append(logs, receipt.Logs...)
}
}
kv = append(kv, receipt.KV...)
logs = append(logs, receipt.Logs...)
//op reward
fundOp := int64(factor*decimal) * totalFund * lott.OpRewardRatio / rewardBase
receipt, err := action.coinsAccount.ExecTransferFrozen(lott.CreateAddr, opRewardAddr, action.execaddr, fundOp)
if err != nil {
return nil, nil, err
}
kv = append(kv, receipt.KV...)
logs = append(logs, receipt.Logs...)
//dev reward
fundDev := int64(factor*decimal) * totalFund * lott.DevRewardRatio / rewardBase
receipt, err = action.coinsAccount.ExecTransferFrozen(lott.CreateAddr, devRewardAddr, action.execaddr, fundDev)
if err != nil {
return nil, nil, err
}
kv = append(kv, receipt.KV...)
logs = append(logs, receipt.Logs...)
}
for addr := range lott.Records {
lott.Records[addr].Record = lott.Records[addr].Record[0:0]
delete(lott.Records, addr)
for i := range lott.PurRecords {
lott.PurRecords[i].Record = lott.PurRecords[i].Record[0:0]
}
lott.PurRecords = lott.PurRecords[0:0]
llog.Debug("checkDraw lottery switch to drawed")
lott.LastTransToDrawState = action.height
......@@ -685,7 +682,7 @@ func (action *Action) checkDraw(lott *LotteryDB) (*types.Receipt, *pty.LotteryUp
if types.IsPara() {
mainHeight := action.GetMainHeightByTxHash(action.txhash)
if mainHeight < 0 {
llog.Error("LotteryBuy", "mainHeight", mainHeight)
llog.Error("LotteryDraw", "mainHeight", mainHeight)
return nil, nil, pty.ErrLotteryStatus
}
lott.LastTransToDrawStateOnMain = mainHeight
......
......@@ -16,9 +16,11 @@ func (l *Lottery) Query_GetLotteryNormalInfo(param *pty.ReqLotteryInfo) (types.M
return nil, err
}
return &pty.ReplyLotteryNormalInfo{CreateHeight: lottery.CreateHeight,
PurBlockNum: lottery.PurBlockNum,
DrawBlockNum: lottery.DrawBlockNum,
CreateAddr: lottery.CreateAddr}, nil
PurBlockNum: lottery.PurBlockNum,
DrawBlockNum: lottery.DrawBlockNum,
CreateAddr: lottery.CreateAddr,
OpRewardRatio: lottery.OpRewardRatio,
DevRewardRatio: lottery.DevRewardRatio}, nil
}
// Query_GetLotteryPurchaseAddr for current round
......@@ -28,8 +30,8 @@ func (l *Lottery) Query_GetLotteryPurchaseAddr(param *pty.ReqLotteryInfo) (types
return nil, err
}
reply := &pty.ReplyLotteryPurchaseAddr{}
for addr := range lottery.Records {
reply.Address = append(reply.Address, addr)
for _, recs := range lottery.PurRecords {
reply.Address = append(reply.Address, recs.Addr)
}
//lottery.Records
return reply, nil
......
......@@ -13,6 +13,7 @@ message PurchaseRecords {
repeated PurchaseRecord record = 1;
int64 fundWin = 2;
int64 amountOneRound = 3;
string addr = 4;
}
message Lottery {
......@@ -24,7 +25,7 @@ message Lottery {
int64 drawBlockNum = 6;
int64 lastTransToPurState = 7;
int64 lastTransToDrawState = 8;
map<string, PurchaseRecords> records = 9;
//map<string, PurchaseRecords> records = 9;
int64 totalPurchasedTxNum = 10;
string createAddr = 11;
int64 round = 12;
......@@ -33,6 +34,9 @@ message Lottery {
int64 lastTransToPurStateOnMain = 15;
int64 lastTransToDrawStateOnMain = 16;
repeated MissingRecord missingRecords = 17;
int64 opRewardRatio = 18;
int64 devRewardRatio = 19;
repeated PurchaseRecords purRecords = 20;
}
message MissingRecord {
......@@ -50,8 +54,10 @@ message LotteryAction {
}
message LotteryCreate {
int64 purBlockNum = 1;
int64 drawBlockNum = 2;
int64 purBlockNum = 1;
int64 drawBlockNum = 2;
int64 opRewardRatio = 3;
int64 devRewardRatio = 4;
}
message LotteryBuy {
......@@ -117,10 +123,12 @@ message ReqLotteryLuckyHistory {
}
message ReplyLotteryNormalInfo {
int64 createHeight = 1;
int64 purBlockNum = 2;
int64 drawBlockNum = 3;
string createAddr = 4;
int64 createHeight = 1;
int64 purBlockNum = 2;
int64 drawBlockNum = 3;
string createAddr = 4;
int64 opRewardRatio = 5;
int64 devRewardRatio = 6;
}
message ReplyLotteryCurrentInfo {
......
......@@ -25,4 +25,5 @@ var (
ErrLotteryErrUnableClose = errors.New("ErrLotteryErrUnableClose")
ErrNodeNotExist = errors.New("ErrNodeNotExist")
ErrEmptyMinerTx = errors.New("ErrEmptyMinerTx")
ErrRewardFactor = errors.New("ErrRewardFactor")
)
......@@ -109,8 +109,10 @@ func CreateRawLotteryCreateTx(parm *LotteryCreateTx) (*types.Transaction, error)
}
v := &LotteryCreate{
PurBlockNum: parm.PurBlockNum,
DrawBlockNum: parm.DrawBlockNum,
PurBlockNum: parm.PurBlockNum,
DrawBlockNum: parm.DrawBlockNum,
OpRewardRatio: parm.OpRewardRatio,
DevRewardRatio: parm.DevRewardRatio,
}
create := &LotteryAction{
Ty: LotteryActionCreate,
......
......@@ -88,6 +88,7 @@ type PurchaseRecords struct {
Record []*PurchaseRecord `protobuf:"bytes,1,rep,name=record,proto3" json:"record,omitempty"`
FundWin int64 `protobuf:"varint,2,opt,name=fundWin,proto3" json:"fundWin,omitempty"`
AmountOneRound int64 `protobuf:"varint,3,opt,name=amountOneRound,proto3" json:"amountOneRound,omitempty"`
Addr string `protobuf:"bytes,4,opt,name=addr,proto3" json:"addr,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
......@@ -139,27 +140,37 @@ func (m *PurchaseRecords) GetAmountOneRound() int64 {
return 0
}
func (m *PurchaseRecords) GetAddr() string {
if m != nil {
return m.Addr
}
return ""
}
type Lottery struct {
LotteryId string `protobuf:"bytes,1,opt,name=lotteryId,proto3" json:"lotteryId,omitempty"`
Status int32 `protobuf:"varint,2,opt,name=status,proto3" json:"status,omitempty"`
CreateHeight int64 `protobuf:"varint,3,opt,name=createHeight,proto3" json:"createHeight,omitempty"`
Fund int64 `protobuf:"varint,4,opt,name=fund,proto3" json:"fund,omitempty"`
PurBlockNum int64 `protobuf:"varint,5,opt,name=purBlockNum,proto3" json:"purBlockNum,omitempty"`
DrawBlockNum int64 `protobuf:"varint,6,opt,name=drawBlockNum,proto3" json:"drawBlockNum,omitempty"`
LastTransToPurState int64 `protobuf:"varint,7,opt,name=lastTransToPurState,proto3" json:"lastTransToPurState,omitempty"`
LastTransToDrawState int64 `protobuf:"varint,8,opt,name=lastTransToDrawState,proto3" json:"lastTransToDrawState,omitempty"`
Records map[string]*PurchaseRecords `protobuf:"bytes,9,rep,name=records,proto3" json:"records,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
TotalPurchasedTxNum int64 `protobuf:"varint,10,opt,name=totalPurchasedTxNum,proto3" json:"totalPurchasedTxNum,omitempty"`
CreateAddr string `protobuf:"bytes,11,opt,name=createAddr,proto3" json:"createAddr,omitempty"`
Round int64 `protobuf:"varint,12,opt,name=round,proto3" json:"round,omitempty"`
LuckyNumber int64 `protobuf:"varint,13,opt,name=luckyNumber,proto3" json:"luckyNumber,omitempty"`
CreateOnMain int64 `protobuf:"varint,14,opt,name=createOnMain,proto3" json:"createOnMain,omitempty"`
LastTransToPurStateOnMain int64 `protobuf:"varint,15,opt,name=lastTransToPurStateOnMain,proto3" json:"lastTransToPurStateOnMain,omitempty"`
LastTransToDrawStateOnMain int64 `protobuf:"varint,16,opt,name=lastTransToDrawStateOnMain,proto3" json:"lastTransToDrawStateOnMain,omitempty"`
MissingRecords []*MissingRecord `protobuf:"bytes,17,rep,name=missingRecords,proto3" json:"missingRecords,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
LotteryId string `protobuf:"bytes,1,opt,name=lotteryId,proto3" json:"lotteryId,omitempty"`
Status int32 `protobuf:"varint,2,opt,name=status,proto3" json:"status,omitempty"`
CreateHeight int64 `protobuf:"varint,3,opt,name=createHeight,proto3" json:"createHeight,omitempty"`
Fund int64 `protobuf:"varint,4,opt,name=fund,proto3" json:"fund,omitempty"`
PurBlockNum int64 `protobuf:"varint,5,opt,name=purBlockNum,proto3" json:"purBlockNum,omitempty"`
DrawBlockNum int64 `protobuf:"varint,6,opt,name=drawBlockNum,proto3" json:"drawBlockNum,omitempty"`
LastTransToPurState int64 `protobuf:"varint,7,opt,name=lastTransToPurState,proto3" json:"lastTransToPurState,omitempty"`
LastTransToDrawState int64 `protobuf:"varint,8,opt,name=lastTransToDrawState,proto3" json:"lastTransToDrawState,omitempty"`
//map<string, PurchaseRecords> records = 9;
TotalPurchasedTxNum int64 `protobuf:"varint,10,opt,name=totalPurchasedTxNum,proto3" json:"totalPurchasedTxNum,omitempty"`
CreateAddr string `protobuf:"bytes,11,opt,name=createAddr,proto3" json:"createAddr,omitempty"`
Round int64 `protobuf:"varint,12,opt,name=round,proto3" json:"round,omitempty"`
LuckyNumber int64 `protobuf:"varint,13,opt,name=luckyNumber,proto3" json:"luckyNumber,omitempty"`
CreateOnMain int64 `protobuf:"varint,14,opt,name=createOnMain,proto3" json:"createOnMain,omitempty"`
LastTransToPurStateOnMain int64 `protobuf:"varint,15,opt,name=lastTransToPurStateOnMain,proto3" json:"lastTransToPurStateOnMain,omitempty"`
LastTransToDrawStateOnMain int64 `protobuf:"varint,16,opt,name=lastTransToDrawStateOnMain,proto3" json:"lastTransToDrawStateOnMain,omitempty"`
MissingRecords []*MissingRecord `protobuf:"bytes,17,rep,name=missingRecords,proto3" json:"missingRecords,omitempty"`
OpRewardRatio int64 `protobuf:"varint,18,opt,name=opRewardRatio,proto3" json:"opRewardRatio,omitempty"`
DevRewardRatio int64 `protobuf:"varint,19,opt,name=devRewardRatio,proto3" json:"devRewardRatio,omitempty"`
PurRecords []*PurchaseRecords `protobuf:"bytes,20,rep,name=purRecords,proto3" json:"purRecords,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Lottery) Reset() { *m = Lottery{} }
......@@ -243,13 +254,6 @@ func (m *Lottery) GetLastTransToDrawState() int64 {
return 0
}
func (m *Lottery) GetRecords() map[string]*PurchaseRecords {
if m != nil {
return m.Records
}
return nil
}
func (m *Lottery) GetTotalPurchasedTxNum() int64 {
if m != nil {
return m.TotalPurchasedTxNum
......@@ -306,6 +310,27 @@ func (m *Lottery) GetMissingRecords() []*MissingRecord {
return nil
}
func (m *Lottery) GetOpRewardRatio() int64 {
if m != nil {
return m.OpRewardRatio
}
return 0
}
func (m *Lottery) GetDevRewardRatio() int64 {
if m != nil {
return m.DevRewardRatio
}
return 0
}
func (m *Lottery) GetPurRecords() []*PurchaseRecords {
if m != nil {
return m.PurRecords
}
return nil
}
type MissingRecord struct {
Times []int32 `protobuf:"varint,1,rep,packed,name=times,proto3" json:"times,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
......@@ -568,6 +593,8 @@ func _LotteryAction_OneofSizer(msg proto.Message) (n int) {
type LotteryCreate struct {
PurBlockNum int64 `protobuf:"varint,1,opt,name=purBlockNum,proto3" json:"purBlockNum,omitempty"`
DrawBlockNum int64 `protobuf:"varint,2,opt,name=drawBlockNum,proto3" json:"drawBlockNum,omitempty"`
OpRewardRatio int64 `protobuf:"varint,3,opt,name=opRewardRatio,proto3" json:"opRewardRatio,omitempty"`
DevRewardRatio int64 `protobuf:"varint,4,opt,name=devRewardRatio,proto3" json:"devRewardRatio,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
......@@ -612,6 +639,20 @@ func (m *LotteryCreate) GetDrawBlockNum() int64 {
return 0
}
func (m *LotteryCreate) GetOpRewardRatio() int64 {
if m != nil {
return m.OpRewardRatio
}
return 0
}
func (m *LotteryCreate) GetDevRewardRatio() int64 {
if m != nil {
return m.DevRewardRatio
}
return 0
}
type LotteryBuy struct {
LotteryId string `protobuf:"bytes,1,opt,name=lotteryId,proto3" json:"lotteryId,omitempty"`
Amount int64 `protobuf:"varint,2,opt,name=amount,proto3" json:"amount,omitempty"`
......@@ -1176,6 +1217,8 @@ type ReplyLotteryNormalInfo struct {
PurBlockNum int64 `protobuf:"varint,2,opt,name=purBlockNum,proto3" json:"purBlockNum,omitempty"`
DrawBlockNum int64 `protobuf:"varint,3,opt,name=drawBlockNum,proto3" json:"drawBlockNum,omitempty"`
CreateAddr string `protobuf:"bytes,4,opt,name=createAddr,proto3" json:"createAddr,omitempty"`
OpRewardRatio int64 `protobuf:"varint,5,opt,name=opRewardRatio,proto3" json:"opRewardRatio,omitempty"`
DevRewardRatio int64 `protobuf:"varint,6,opt,name=devRewardRatio,proto3" json:"devRewardRatio,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
......@@ -1234,6 +1277,20 @@ func (m *ReplyLotteryNormalInfo) GetCreateAddr() string {
return ""
}
func (m *ReplyLotteryNormalInfo) GetOpRewardRatio() int64 {
if m != nil {
return m.OpRewardRatio
}
return 0
}
func (m *ReplyLotteryNormalInfo) GetDevRewardRatio() int64 {
if m != nil {
return m.DevRewardRatio
}
return 0
}
type ReplyLotteryCurrentInfo struct {
Status int32 `protobuf:"varint,1,opt,name=status,proto3" json:"status,omitempty"`
Fund int64 `protobuf:"varint,2,opt,name=fund,proto3" json:"fund,omitempty"`
......@@ -1891,7 +1948,6 @@ func init() {
proto.RegisterType((*PurchaseRecord)(nil), "types.PurchaseRecord")
proto.RegisterType((*PurchaseRecords)(nil), "types.PurchaseRecords")
proto.RegisterType((*Lottery)(nil), "types.Lottery")
proto.RegisterMapType((map[string]*PurchaseRecords)(nil), "types.Lottery.RecordsEntry")
proto.RegisterType((*MissingRecord)(nil), "types.MissingRecord")
proto.RegisterType((*LotteryAction)(nil), "types.LotteryAction")
proto.RegisterType((*LotteryCreate)(nil), "types.LotteryCreate")
......@@ -1923,84 +1979,86 @@ func init() {
func init() { proto.RegisterFile("lottery.proto", fileDescriptor_2cce7afd61783b10) }
var fileDescriptor_2cce7afd61783b10 = []byte{
// 1252 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x58, 0x5f, 0x6f, 0xe3, 0x44,
0x10, 0xaf, 0xed, 0x38, 0x69, 0x26, 0x69, 0xee, 0xba, 0x2d, 0x3d, 0x53, 0x50, 0x55, 0x59, 0x3a,
0x54, 0xe9, 0x8e, 0x08, 0x02, 0x48, 0x08, 0x2a, 0xa4, 0xcb, 0x71, 0x28, 0x95, 0x7a, 0xbd, 0xd3,
0xb6, 0x27, 0x1e, 0x78, 0x72, 0xe3, 0xbd, 0xab, 0xd5, 0xc4, 0x0e, 0xf6, 0xfa, 0x5a, 0xbf, 0x21,
0xbe, 0x04, 0x3c, 0xf3, 0xc4, 0x23, 0x1f, 0x81, 0x4f, 0xc1, 0x17, 0xe1, 0x0b, 0xa0, 0x9d, 0x5d,
0xc7, 0x6b, 0xc7, 0x49, 0x7a, 0xdc, 0x53, 0x76, 0x67, 0x67, 0x67, 0x67, 0x7e, 0xf3, 0xd7, 0x81,
0xad, 0x49, 0xc4, 0x39, 0x8b, 0xb3, 0xfe, 0x2c, 0x8e, 0x78, 0x44, 0x6c, 0x9e, 0xcd, 0x58, 0xe2,
0x5e, 0x41, 0xef, 0x65, 0x1a, 0x8f, 0xaf, 0xbc, 0x84, 0x51, 0x36, 0x8e, 0x62, 0x9f, 0xec, 0x41,
0xd3, 0x9b, 0x46, 0x69, 0xc8, 0x1d, 0xe3, 0xd0, 0x38, 0xb2, 0xa8, 0xda, 0x09, 0x7a, 0x98, 0x4e,
0x2f, 0x59, 0xec, 0x98, 0x92, 0x2e, 0x77, 0x64, 0x17, 0xec, 0x20, 0xf4, 0xd9, 0xad, 0x63, 0x21,
0x59, 0x6e, 0xc8, 0x7d, 0xb0, 0x6e, 0xbc, 0xcc, 0x69, 0x20, 0x4d, 0x2c, 0xdd, 0x5f, 0x0d, 0xb8,
0x57, 0x7e, 0x2a, 0x21, 0x9f, 0x42, 0x33, 0xc6, 0xa5, 0x63, 0x1c, 0x5a, 0x47, 0x9d, 0xc1, 0x07,
0x7d, 0xd4, 0xaa, 0x5f, 0xe6, 0xa3, 0x8a, 0x89, 0x38, 0xd0, 0x7a, 0x9d, 0x86, 0xfe, 0x8f, 0x41,
0xa8, 0x74, 0xc8, 0xb7, 0xe4, 0x13, 0xe8, 0x49, 0x35, 0x5f, 0x84, 0x8c, 0x46, 0x69, 0xe8, 0x2b,
0x6d, 0x2a, 0x54, 0xf7, 0xf7, 0x26, 0xb4, 0x4e, 0x25, 0x0e, 0xe4, 0x63, 0x68, 0x2b, 0x48, 0x4e,
0x7c, 0xb4, 0xb5, 0x4d, 0x0b, 0x82, 0x30, 0x37, 0xe1, 0x1e, 0x4f, 0x13, 0x7c, 0xca, 0xa6, 0x6a,
0x47, 0x5c, 0xe8, 0x8e, 0x63, 0xe6, 0x71, 0x36, 0x62, 0xc1, 0x9b, 0x2b, 0xae, 0xde, 0x29, 0xd1,
0x08, 0x81, 0x86, 0x50, 0x4c, 0x59, 0x8f, 0x6b, 0x72, 0x08, 0x9d, 0x59, 0x1a, 0x0f, 0x27, 0xd1,
0xf8, 0xfa, 0x2c, 0x9d, 0x3a, 0x36, 0x1e, 0xe9, 0x24, 0x21, 0xd9, 0x8f, 0xbd, 0x9b, 0x39, 0x4b,
0x53, 0x4a, 0xd6, 0x69, 0xe4, 0x33, 0xd8, 0x99, 0x78, 0x09, 0xbf, 0x88, 0xbd, 0x30, 0xb9, 0x88,
0x5e, 0xa6, 0xf1, 0x39, 0xf7, 0x38, 0x73, 0x5a, 0xc8, 0x5a, 0x77, 0x44, 0x06, 0xb0, 0xab, 0x91,
0xbf, 0x8f, 0xbd, 0x1b, 0x79, 0x65, 0x13, 0xaf, 0xd4, 0x9e, 0x91, 0xaf, 0xa0, 0x25, 0x11, 0x4f,
0x9c, 0x36, 0xfa, 0xe5, 0x23, 0xe5, 0x17, 0x05, 0x5d, 0x5f, 0xf9, 0xef, 0x59, 0xc8, 0xe3, 0x8c,
0xe6, 0xbc, 0x42, 0x39, 0x1e, 0x71, 0x6f, 0x92, 0x7b, 0xcf, 0xbf, 0xb8, 0x15, 0x76, 0x80, 0x54,
0xae, 0xe6, 0x88, 0x1c, 0x00, 0x48, 0xe0, 0x9e, 0xf8, 0x7e, 0xec, 0x74, 0xd0, 0x07, 0x1a, 0x45,
0xc4, 0x56, 0x8c, 0xde, 0xec, 0xca, 0xd8, 0xc2, 0x8d, 0x80, 0x72, 0x92, 0x8e, 0xaf, 0xb3, 0x33,
0x19, 0x8e, 0x5b, 0x12, 0x4a, 0x8d, 0x54, 0x38, 0xe9, 0x45, 0xf8, 0xdc, 0x0b, 0x42, 0xa7, 0xa7,
0x3b, 0x49, 0xd2, 0xc8, 0x31, 0x7c, 0x58, 0x83, 0x97, 0xba, 0x70, 0x0f, 0x2f, 0x2c, 0x67, 0x20,
0xdf, 0xc1, 0x7e, 0x1d, 0x74, 0xea, 0xfa, 0x7d, 0xbc, 0xbe, 0x82, 0x83, 0x1c, 0x43, 0x6f, 0x1a,
0x24, 0x49, 0x10, 0xbe, 0x51, 0x58, 0x3a, 0xdb, 0x88, 0xf4, 0xae, 0x42, 0xfa, 0xb9, 0x7e, 0x48,
0x2b, 0xbc, 0xfb, 0x14, 0xba, 0xba, 0x0b, 0x44, 0xb6, 0x5d, 0xb3, 0x4c, 0x05, 0xb1, 0x58, 0x92,
0xc7, 0x60, 0xbf, 0xf5, 0x26, 0x29, 0xc3, 0xe8, 0xed, 0x0c, 0xf6, 0x6a, 0x13, 0x2b, 0xa1, 0x92,
0xe9, 0x1b, 0xf3, 0x6b, 0xc3, 0x7d, 0x08, 0x5b, 0xa5, 0x47, 0x05, 0xf8, 0x3c, 0x98, 0xb2, 0x04,
0x73, 0xd3, 0xa6, 0x72, 0xe3, 0xfe, 0x63, 0xc0, 0x96, 0x0a, 0x83, 0x27, 0x63, 0x1e, 0x44, 0x21,
0xe9, 0x43, 0x53, 0x02, 0x8b, 0xef, 0x17, 0x26, 0x28, 0xae, 0xa7, 0x32, 0x33, 0x36, 0xa8, 0xe2,
0x22, 0x0f, 0xc1, 0xba, 0x4c, 0x33, 0xa5, 0xd8, 0x76, 0x99, 0x79, 0x98, 0x66, 0xa3, 0x0d, 0x2a,
0xce, 0xc9, 0x11, 0x34, 0x44, 0xe8, 0x63, 0x82, 0x75, 0x06, 0xa4, 0xcc, 0x27, 0xe0, 0x1c, 0x6d,
0x50, 0xe4, 0x20, 0x8f, 0xc0, 0x1e, 0x4f, 0xa2, 0x84, 0x61, 0xbe, 0x75, 0x06, 0x3b, 0x95, 0xf7,
0xc5, 0xd1, 0x68, 0x83, 0x4a, 0x1e, 0xd2, 0x03, 0x93, 0x67, 0x18, 0x93, 0x36, 0x35, 0x79, 0x36,
0x6c, 0x29, 0xa0, 0xdc, 0x57, 0x73, 0xbb, 0xa4, 0xc6, 0xd5, 0x8c, 0x35, 0xd6, 0x67, 0xac, 0xb9,
0x98, 0xb1, 0xee, 0x04, 0xa0, 0xb0, 0x6d, 0x7d, 0xcd, 0x51, 0xa5, 0xd7, 0x5c, 0x52, 0x7a, 0xad,
0x52, 0xe9, 0x5d, 0x2c, 0xb2, 0x8f, 0xa0, 0xa3, 0x21, 0xb4, 0xfa, 0x39, 0xf7, 0x31, 0x74, 0x75,
0x8c, 0xd6, 0x70, 0xff, 0x6b, 0x42, 0x8f, 0xb2, 0x31, 0x0b, 0x66, 0xfc, 0xfd, 0x2a, 0xe8, 0x01,
0xc0, 0x2c, 0x66, 0x6f, 0xcf, 0xe5, 0x99, 0x85, 0x67, 0x1a, 0x45, 0x54, 0x4f, 0x4f, 0x94, 0x83,
0x06, 0x0a, 0xc4, 0x75, 0x51, 0x08, 0x6c, 0xbd, 0x10, 0x14, 0xb8, 0x34, 0x4b, 0xb8, 0x14, 0x38,
0xb6, 0x4a, 0x38, 0x56, 0x0a, 0xc7, 0xe6, 0x62, 0xe1, 0x20, 0xd0, 0x10, 0x61, 0xee, 0xb4, 0x65,
0xe5, 0x16, 0x6b, 0x21, 0x8d, 0xdf, 0x8e, 0xbc, 0xe4, 0x0a, 0xa3, 0xa6, 0x4d, 0xd5, 0x8e, 0x7c,
0x0b, 0x90, 0xce, 0x7c, 0x8f, 0xb3, 0x93, 0xf0, 0x75, 0x84, 0xc5, 0x6b, 0xa1, 0x50, 0xbe, 0xc2,
0xf3, 0x61, 0x9a, 0x09, 0x16, 0xaa, 0xb1, 0xe7, 0xae, 0xeb, 0xce, 0x5d, 0x57, 0xf4, 0xd1, 0x2d,
0xad, 0x8f, 0xba, 0x7d, 0x01, 0xfa, 0xcf, 0x4a, 0x1c, 0xde, 0x5c, 0xed, 0xa5, 0x9f, 0x60, 0xbb,
0xe0, 0x57, 0x0f, 0xaf, 0xf1, 0x53, 0x8e, 0xb7, 0x59, 0x87, 0xb7, 0xa5, 0xe1, 0xed, 0xfe, 0x69,
0xc0, 0x6e, 0x49, 0xfa, 0x28, 0x48, 0x78, 0xb4, 0x36, 0x10, 0xee, 0xfc, 0x80, 0xa0, 0x8e, 0xd1,
0x6f, 0x0d, 0x8c, 0x0a, 0xb9, 0x11, 0xd2, 0xfd, 0x20, 0x66, 0x58, 0x6d, 0x30, 0x00, 0x6c, 0x5a,
0x10, 0x0a, 0xdc, 0x9a, 0x3a, 0x6e, 0x27, 0xb0, 0x53, 0x68, 0x7a, 0x2a, 0x3c, 0x7c, 0x07, 0x24,
0xe6, 0x4a, 0x99, 0x87, 0x56, 0x61, 0xf5, 0x2f, 0x06, 0xec, 0x55, 0x64, 0xdd, 0xcd, 0x6e, 0x4d,
0x5c, 0x9d, 0x8d, 0xd6, 0x52, 0x1b, 0x1b, 0x15, 0x1b, 0xdd, 0x3f, 0x50, 0x85, 0xd9, 0x24, 0x53,
0x4a, 0x9c, 0x45, 0xf1, 0xd4, 0x9b, 0xa0, 0x45, 0xd5, 0x79, 0xc4, 0xa8, 0x99, 0x47, 0x2a, 0x95,
0xcc, 0x5c, 0x5f, 0xc9, 0xac, 0x9a, 0xd9, 0xa3, 0xdc, 0xac, 0x1b, 0xd5, 0x66, 0xed, 0xfe, 0xd6,
0x80, 0x07, 0xba, 0x92, 0x4f, 0xd3, 0x38, 0x66, 0x21, 0x47, 0x2d, 0x8b, 0x5a, 0x60, 0x94, 0x6a,
0x41, 0x3e, 0x29, 0x99, 0xda, 0xa4, 0xb4, 0x64, 0xc6, 0xb1, 0xde, 0x7d, 0xc6, 0x69, 0xac, 0x98,
0x71, 0x96, 0x0c, 0x2b, 0xf6, 0xf2, 0x61, 0x65, 0xee, 0xce, 0xe6, 0x8a, 0x61, 0xa4, 0xb5, 0x58,
0x53, 0x56, 0x0e, 0x1a, 0x9b, 0xef, 0x37, 0x68, 0xb4, 0xd7, 0x0e, 0x1a, 0x15, 0xdf, 0xc3, 0x7a,
0xdf, 0x77, 0x6a, 0x7c, 0xbf, 0x38, 0xae, 0x74, 0xef, 0x3e, 0xae, 0xb8, 0x43, 0x38, 0xd0, 0x03,
0x43, 0x65, 0xcf, 0xa9, 0x86, 0x51, 0x05, 0x45, 0x03, 0xf3, 0x4f, 0x27, 0xb9, 0x27, 0xa2, 0xf4,
0x14, 0x32, 0xce, 0xaf, 0xa2, 0x1b, 0x8c, 0xac, 0xcf, 0x8b, 0x59, 0x55, 0x7e, 0x43, 0x3c, 0x58,
0x98, 0x28, 0x94, 0x56, 0x39, 0x9f, 0xfb, 0x0c, 0x76, 0xf2, 0x3c, 0x42, 0xd9, 0xc5, 0x87, 0x4f,
0x98, 0x3f, 0x5f, 0xdf, 0x4d, 0x4a, 0x5d, 0xd9, 0xfd, 0xdb, 0x80, 0xfb, 0xd5, 0x47, 0xde, 0x55,
0xc8, 0x92, 0x3a, 0x28, 0xda, 0x50, 0x36, 0xcb, 0x03, 0x18, 0xd7, 0x79, 0xc7, 0xb0, 0x6b, 0x3a,
0x86, 0x5e, 0xf9, 0xe6, 0x2d, 0xac, 0x55, 0xdb, 0xc2, 0x36, 0xf5, 0x16, 0xe6, 0xfe, 0x00, 0xdb,
0x55, 0x0b, 0x92, 0xff, 0x83, 0xe8, 0x74, 0x2e, 0x47, 0x84, 0xdf, 0x1a, 0x28, 0xea, 0xcb, 0x62,
0xae, 0xb6, 0x55, 0xab, 0x76, 0xa3, 0xa4, 0xf6, 0x08, 0xc8, 0xc2, 0x73, 0x09, 0x19, 0x54, 0xf5,
0x76, 0x16, 0x67, 0xc6, 0xaa, 0xe2, 0xc7, 0x73, 0x17, 0xca, 0x56, 0x4d, 0xd9, 0xb8, 0x80, 0xd5,
0xa8, 0xc2, 0x2a, 0x5c, 0x62, 0x16, 0x2e, 0xd1, 0xe0, 0x9b, 0xdf, 0x5e, 0x0f, 0xdf, 0x9c, 0xb5,
0xd0, 0xe2, 0x2f, 0x03, 0x76, 0xeb, 0x26, 0x06, 0x32, 0x84, 0xd6, 0xa5, 0x5c, 0x2a, 0x59, 0x47,
0x2b, 0xe6, 0x8b, 0xbe, 0xfa, 0x55, 0x5f, 0x65, 0xea, 0xe2, 0xfe, 0x05, 0x74, 0xf5, 0x83, 0x9a,
0x6f, 0x85, 0x7e, 0xf9, 0x5b, 0xc1, 0x59, 0xa2, 0x6f, 0xe9, 0x6b, 0xe1, 0x4b, 0x70, 0xf4, 0x74,
0xcc, 0x4b, 0x25, 0x7e, 0xb5, 0x39, 0xd0, 0x12, 0x3d, 0x9e, 0x25, 0x12, 0x81, 0x36, 0xcd, 0xb7,
0x97, 0x4d, 0xfc, 0xef, 0xe1, 0x8b, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0xb7, 0x56, 0x83, 0xf5,
0x8c, 0x10, 0x00, 0x00,
// 1285 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x58, 0xdd, 0x6e, 0xe3, 0x44,
0x14, 0xae, 0xed, 0x38, 0x69, 0x4e, 0x7e, 0xb6, 0x9d, 0x86, 0xae, 0x59, 0x50, 0x55, 0x59, 0x2c,
0xaa, 0xb4, 0x10, 0x41, 0x40, 0x08, 0x41, 0x85, 0xb4, 0x59, 0x16, 0xa5, 0x52, 0xb7, 0xbb, 0x9a,
0x16, 0x71, 0xc1, 0x95, 0x1b, 0xcf, 0x6e, 0xad, 0x26, 0x76, 0x18, 0x8f, 0xdb, 0xfa, 0x8e, 0x77,
0x40, 0x82, 0x07, 0xe0, 0x86, 0x4b, 0x1e, 0x81, 0xa7, 0xe0, 0x39, 0x90, 0x78, 0x01, 0x34, 0x3f,
0x8e, 0xc7, 0x8e, 0xf3, 0x53, 0xf6, 0xaa, 0x9e, 0x33, 0x67, 0xe6, 0x9c, 0xf9, 0xce, 0x39, 0xdf,
0x39, 0x29, 0x74, 0x26, 0x11, 0x63, 0x84, 0xa6, 0xfd, 0x19, 0x8d, 0x58, 0x84, 0x6c, 0x96, 0xce,
0x48, 0xec, 0x5e, 0x41, 0xf7, 0x55, 0x42, 0xc7, 0x57, 0x5e, 0x4c, 0x30, 0x19, 0x47, 0xd4, 0x47,
0xfb, 0x50, 0xf7, 0xa6, 0x51, 0x12, 0x32, 0xc7, 0x38, 0x34, 0x8e, 0x2c, 0xac, 0x56, 0x5c, 0x1e,
0x26, 0xd3, 0x4b, 0x42, 0x1d, 0x53, 0xca, 0xe5, 0x0a, 0xf5, 0xc0, 0x0e, 0x42, 0x9f, 0xdc, 0x39,
0x96, 0x10, 0xcb, 0x05, 0xda, 0x01, 0xeb, 0xd6, 0x4b, 0x9d, 0x9a, 0x90, 0xf1, 0x4f, 0xf7, 0x57,
0x03, 0x1e, 0x14, 0x4d, 0xc5, 0xe8, 0x63, 0xa8, 0x53, 0xf1, 0xe9, 0x18, 0x87, 0xd6, 0x51, 0x6b,
0xf0, 0x4e, 0x5f, 0x78, 0xd5, 0x2f, 0xea, 0x61, 0xa5, 0x84, 0x1c, 0x68, 0xbc, 0x4e, 0x42, 0xff,
0x87, 0x20, 0x54, 0x3e, 0x64, 0x4b, 0xf4, 0x21, 0x74, 0xa5, 0x9b, 0x2f, 0x43, 0x82, 0xa3, 0x24,
0xf4, 0x95, 0x37, 0x25, 0x29, 0x42, 0x50, 0xf3, 0x7c, 0x9f, 0x0a, 0xbf, 0x9a, 0x58, 0x7c, 0xbb,
0xbf, 0xd4, 0xa1, 0x71, 0x2a, 0xb1, 0x41, 0xef, 0x43, 0x53, 0xc1, 0x74, 0xe2, 0x8b, 0xf7, 0x37,
0x71, 0x2e, 0xe0, 0x10, 0xc4, 0xcc, 0x63, 0x49, 0x2c, 0xcc, 0xdb, 0x58, 0xad, 0x90, 0x0b, 0xed,
0x31, 0x25, 0x1e, 0x23, 0x23, 0x12, 0xbc, 0xb9, 0x62, 0xca, 0x76, 0x41, 0xc6, 0x2d, 0x73, 0x67,
0x15, 0x22, 0xe2, 0x1b, 0x1d, 0x42, 0x6b, 0x96, 0xd0, 0xe1, 0x24, 0x1a, 0x5f, 0x9f, 0x25, 0x53,
0xc7, 0x16, 0x5b, 0xba, 0x88, 0xdf, 0xec, 0x53, 0xef, 0x76, 0xae, 0x52, 0x97, 0x37, 0xeb, 0x32,
0xf4, 0x09, 0xec, 0x4d, 0xbc, 0x98, 0x5d, 0x50, 0x2f, 0x8c, 0x2f, 0xa2, 0x57, 0x09, 0x3d, 0x67,
0x1e, 0x23, 0x4e, 0x43, 0xa8, 0x56, 0x6d, 0xa1, 0x01, 0xf4, 0x34, 0xf1, 0xb7, 0xd4, 0xbb, 0x95,
0x47, 0xb6, 0xc5, 0x91, 0xca, 0x3d, 0x6e, 0x85, 0x45, 0xcc, 0x9b, 0x64, 0xa1, 0xf1, 0x2f, 0xee,
0xb8, 0x43, 0x20, 0xad, 0x54, 0x6c, 0xa1, 0x03, 0x00, 0x89, 0xc0, 0x53, 0x8e, 0x78, 0x4b, 0x80,
0xa9, 0x49, 0x78, 0xe2, 0x50, 0x11, 0xaa, 0xb6, 0x4c, 0x1c, 0xb1, 0xe0, 0x98, 0x4c, 0x92, 0xf1,
0x75, 0x7a, 0x26, 0x73, 0xad, 0x23, 0x31, 0xd1, 0x44, 0x39, 0xda, 0x2f, 0xc3, 0x17, 0x5e, 0x10,
0x3a, 0x5d, 0x1d, 0x6d, 0x29, 0x43, 0xc7, 0xf0, 0x6e, 0xc5, 0xc3, 0xd5, 0x81, 0x07, 0xe2, 0xc0,
0x72, 0x05, 0xf4, 0x0d, 0x3c, 0xaa, 0xc2, 0x40, 0x1d, 0xdf, 0x11, 0xc7, 0x57, 0x68, 0xa0, 0x63,
0xe8, 0x4e, 0x83, 0x38, 0x0e, 0xc2, 0x37, 0x2a, 0xd1, 0x9d, 0x5d, 0x91, 0xde, 0x3d, 0x95, 0xde,
0x2f, 0xf4, 0x4d, 0x5c, 0xd2, 0x45, 0x1f, 0x40, 0x27, 0x9a, 0x61, 0x72, 0xeb, 0x51, 0x1f, 0x7b,
0x2c, 0x88, 0x1c, 0x24, 0x0c, 0x16, 0x85, 0x3c, 0xe3, 0x7d, 0x72, 0xa3, 0xab, 0xed, 0xc9, 0x8c,
0x2f, 0x4a, 0xd1, 0x17, 0x00, 0xb3, 0x84, 0x66, 0x7e, 0xf4, 0x84, 0x1f, 0xfb, 0x95, 0x65, 0x16,
0x63, 0x4d, 0xd3, 0x7d, 0x0c, 0x9d, 0x82, 0x9b, 0x3c, 0x5c, 0x2c, 0x98, 0x92, 0x58, 0x94, 0xaa,
0x8d, 0xe5, 0xc2, 0xfd, 0xdb, 0x80, 0x8e, 0x2a, 0x9e, 0xa7, 0x63, 0x16, 0x44, 0x21, 0xea, 0x43,
0x5d, 0x86, 0x42, 0xd4, 0x4f, 0xfe, 0x68, 0xa5, 0xf5, 0x4c, 0x16, 0xc5, 0x16, 0x56, 0x5a, 0xe8,
0x31, 0x58, 0x97, 0x49, 0x2a, 0x2a, 0xaa, 0x35, 0xd8, 0x2d, 0x2a, 0x0f, 0x93, 0x74, 0xb4, 0x85,
0xf9, 0x3e, 0x3a, 0x82, 0x1a, 0xcf, 0x7a, 0x51, 0x5b, 0xad, 0x01, 0x2a, 0xea, 0xf1, 0x00, 0x8c,
0xb6, 0xb0, 0xd0, 0x40, 0x4f, 0xc0, 0x1e, 0x4f, 0xa2, 0x98, 0x88, 0x52, 0x6b, 0x0d, 0xf6, 0x4a,
0xf6, 0xf9, 0xd6, 0x68, 0x0b, 0x4b, 0x1d, 0xd4, 0x05, 0x93, 0xa5, 0x22, 0x8b, 0x6d, 0x6c, 0xb2,
0x74, 0xd8, 0x00, 0xfb, 0xc6, 0x9b, 0x24, 0xc4, 0xfd, 0x3d, 0x7f, 0x98, 0x74, 0xb9, 0x5c, 0xad,
0xc6, 0xfa, 0x6a, 0x35, 0x2b, 0xaa, 0x75, 0x21, 0xba, 0xd6, 0x66, 0xd1, 0xad, 0x55, 0x45, 0xd7,
0x9d, 0x00, 0xe4, 0x50, 0xad, 0x67, 0x2f, 0x45, 0xec, 0xe6, 0x12, 0x62, 0xb7, 0x0a, 0xc4, 0xbe,
0x48, 0xe1, 0x4f, 0xa0, 0xa5, 0x01, 0xbe, 0xda, 0x9c, 0xfb, 0x11, 0xb4, 0x75, 0xc8, 0xd7, 0x68,
0xff, 0x6b, 0x42, 0x17, 0x93, 0x31, 0x09, 0x66, 0xec, 0xed, 0xb8, 0xf8, 0x00, 0x60, 0x46, 0xc9,
0xcd, 0xb9, 0xdc, 0xb3, 0xc4, 0x9e, 0x26, 0xa9, 0xea, 0x00, 0x39, 0x13, 0xd9, 0x3a, 0x13, 0xe5,
0xb8, 0xd4, 0x0b, 0xb8, 0xe4, 0x38, 0x36, 0x0a, 0x38, 0x96, 0x98, 0x6b, 0x7b, 0x91, 0xb9, 0x10,
0xd4, 0x78, 0xd5, 0x38, 0x4d, 0xd9, 0x03, 0xf8, 0x37, 0xbf, 0x8d, 0xdd, 0x8d, 0xbc, 0xf8, 0x4a,
0x24, 0x61, 0x13, 0xab, 0x15, 0xfa, 0x1a, 0x20, 0x99, 0xf9, 0x1e, 0x23, 0x27, 0xe1, 0xeb, 0x48,
0xb0, 0x67, 0x6b, 0xf0, 0x5e, 0x31, 0x95, 0xbf, 0x17, 0xfb, 0xc3, 0x24, 0xe5, 0x2a, 0x58, 0x53,
0xcf, 0x42, 0xd7, 0x9e, 0x87, 0x2e, 0xef, 0xd2, 0x1d, 0xad, 0x4b, 0xbb, 0x7d, 0x0e, 0xfa, 0x4f,
0xea, 0x3a, 0x71, 0x72, 0x75, 0x94, 0x7e, 0x84, 0xdd, 0x5c, 0x5f, 0x19, 0x5e, 0x13, 0xa7, 0x0c,
0x6f, 0xb3, 0x0a, 0x6f, 0x4b, 0xc3, 0xdb, 0xfd, 0xc3, 0x80, 0x5e, 0xe1, 0xf6, 0x51, 0x10, 0xb3,
0x68, 0x6d, 0x22, 0x6c, 0x6c, 0x80, 0x4b, 0xc7, 0x22, 0x6e, 0x35, 0x91, 0x15, 0x72, 0xc1, 0x6f,
0xf7, 0x03, 0x4a, 0x04, 0x79, 0x89, 0x04, 0xb0, 0x71, 0x2e, 0xc8, 0x71, 0xab, 0xeb, 0xb8, 0x9d,
0xc0, 0x5e, 0xee, 0xe9, 0x29, 0x8f, 0xf0, 0x06, 0x48, 0xcc, 0x9d, 0x32, 0x0f, 0xad, 0xfc, 0xd5,
0x3f, 0x1b, 0xb0, 0x5f, 0xba, 0x6b, 0xb3, 0x77, 0x6b, 0xd7, 0x55, 0xbd, 0xd1, 0x5a, 0xfa, 0xc6,
0x5a, 0xe9, 0x8d, 0xee, 0x3f, 0xc2, 0x85, 0xd9, 0x24, 0x55, 0x4e, 0x9c, 0x45, 0x74, 0xea, 0x4d,
0xc4, 0x8b, 0xca, 0x93, 0x8d, 0x51, 0x31, 0xd9, 0x94, 0x78, 0xd1, 0x5c, 0xcf, 0x8b, 0x56, 0x05,
0x2f, 0x16, 0xa7, 0x85, 0xda, 0xc2, 0xb4, 0xb0, 0xc0, 0x9b, 0xf6, 0x66, 0xbc, 0x59, 0xaf, 0xe4,
0xcd, 0xdf, 0x6a, 0xf0, 0x50, 0x7f, 0xf2, 0xb3, 0x84, 0x52, 0x12, 0x32, 0xf1, 0xe6, 0x9c, 0x59,
0x8c, 0x02, 0xb3, 0x64, 0x13, 0x9c, 0xa9, 0x4d, 0x70, 0x4b, 0x66, 0x2f, 0xeb, 0xfe, 0xb3, 0x57,
0xed, 0xfe, 0xb3, 0x97, 0xbd, 0x7c, 0xf6, 0x9a, 0x27, 0x47, 0x7d, 0xc5, 0x6c, 0xd5, 0x58, 0x64,
0xa8, 0x95, 0x73, 0xd3, 0xf6, 0xdb, 0xcd, 0x4d, 0xcd, 0xb5, 0x73, 0x53, 0x29, 0x93, 0x60, 0x7d,
0x26, 0xb5, 0x2a, 0x32, 0x69, 0x71, 0xfa, 0x6a, 0x6f, 0x3e, 0x7d, 0xb9, 0x43, 0x38, 0xd0, 0x13,
0x43, 0xd5, 0xe2, 0xa9, 0x86, 0x51, 0x09, 0x45, 0x43, 0x54, 0xb3, 0x2e, 0x72, 0x4f, 0x38, 0x91,
0xe5, 0x77, 0x9c, 0x5f, 0x45, 0xb7, 0x22, 0xb3, 0x3e, 0x85, 0x06, 0x55, 0x2e, 0xc9, 0xdf, 0x3b,
0x0f, 0x17, 0xc6, 0x1d, 0xe5, 0x55, 0xa6, 0xe7, 0x3e, 0x87, 0xbd, 0xac, 0x2a, 0xc5, 0xdd, 0xf9,
0x8f, 0xb4, 0x30, 0x33, 0x5f, 0xdd, 0x9b, 0x0a, 0x3d, 0xde, 0xfd, 0xcb, 0x80, 0x9d, 0xb2, 0x91,
0xfb, 0x5e, 0xb2, 0x84, 0x55, 0x79, 0x53, 0x4b, 0x67, 0x59, 0x02, 0x8b, 0xef, 0xac, 0xff, 0xd8,
0x15, 0xfd, 0x47, 0xe7, 0xd1, 0x79, 0x43, 0x6c, 0x54, 0x36, 0xc4, 0x6d, 0xbd, 0x21, 0xba, 0xdf,
0xc1, 0x6e, 0xf9, 0x05, 0xf1, 0xff, 0x41, 0x74, 0x3a, 0xbf, 0x87, 0xa7, 0xdf, 0x1a, 0x28, 0xaa,
0x49, 0x36, 0x73, 0xdb, 0xaa, 0x74, 0xbb, 0x56, 0x70, 0x7b, 0x04, 0x68, 0xc1, 0x5c, 0x8c, 0x06,
0x65, 0xbf, 0x9d, 0xc5, 0x81, 0xb6, 0xec, 0xf8, 0xf1, 0x3c, 0x84, 0xb2, 0xf1, 0x63, 0x32, 0xce,
0x61, 0x35, 0xca, 0xb0, 0xf2, 0x90, 0x98, 0x79, 0x48, 0x34, 0xf8, 0xe6, 0xa7, 0xd7, 0xc3, 0x37,
0x57, 0xcd, 0xbd, 0xf8, 0xd3, 0x80, 0x5e, 0xd5, 0xfc, 0x81, 0x86, 0xd0, 0xb8, 0x94, 0x9f, 0xea,
0xae, 0xa3, 0x15, 0xd3, 0x4a, 0x5f, 0xfd, 0x7d, 0x1e, 0x32, 0x9a, 0xe2, 0xec, 0xe0, 0xa3, 0x0b,
0x68, 0xeb, 0x1b, 0x3c, 0x8f, 0xae, 0x49, 0xaa, 0x7a, 0x1f, 0xff, 0x44, 0x7d, 0x35, 0x9f, 0xab,
0xdf, 0x0b, 0xce, 0x12, 0x7f, 0x63, 0x2c, 0xd5, 0xbe, 0x32, 0xbf, 0x34, 0xdc, 0xcf, 0xc1, 0xd1,
0xcb, 0x31, 0xa3, 0x4a, 0xd1, 0x56, 0x1c, 0x68, 0xf0, 0x89, 0x81, 0xc4, 0x12, 0x81, 0x26, 0xce,
0x96, 0x97, 0x75, 0xf1, 0x7f, 0x92, 0xcf, 0xfe, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x62, 0x68, 0x00,
0x1f, 0x38, 0x11, 0x00, 0x00,
}
......@@ -6,9 +6,11 @@ package types
// LotteryCreateTx for construction
type LotteryCreateTx struct {
PurBlockNum int64 `json:"purBlockNum"`
DrawBlockNum int64 `json:"drawBlockNum"`
Fee int64 `json:"fee"`
PurBlockNum int64 `json:"purBlockNum"`
DrawBlockNum int64 `json:"drawBlockNum"`
Fee int64 `json:"fee"`
OpRewardRatio int64 `json:"opRewardRatio"`
DevRewardRatio int64 `json:"devRewardRatio"`
}
// LotteryBuyTx for construction
......
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