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
}
This diff is collapsed.
......@@ -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,
......
This diff is collapsed.
......@@ -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