/
ticketnum.go
executable file
·132 lines (116 loc) · 3.99 KB
/
ticketnum.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// 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 (
"fmt"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/types"
tickettypes "github.com/33cn/plugin/plugin/dapp/ticket/types"
)
const (
minBlockNum = 3
maxBlockNum = 10
)
// GetRandNum for ticket executor
func (ticket *Ticket) GetRandNum(blockHash []byte, blockNum int64) (types.Message, error) {
tlog.Debug("GetRandNum", "blockHash", common.ToHex(blockHash), "blockNum", blockNum)
if blockNum < minBlockNum {
blockNum = minBlockNum
} else if blockNum > maxBlockNum {
blockNum = maxBlockNum
}
if len(blockHash) == 0 {
return nil, types.ErrBlockNotFound
}
txActions, err := ticket.getTxActions(blockHash, blockNum)
if err != nil {
return nil, err
}
//如果是genesis block 那么直接返回一个固定值,防止测试的时候出错
if txActions == nil && err == nil {
modify := common.Sha256([]byte("hello"))
return &types.ReplyHash{Hash: modify}, nil
}
var modifies []byte
var bits uint32
var ticketIds string
var privHashs []byte
var vrfHashs []byte
for _, ticketAction := range txActions {
//tlog.Debug("GetRandNum", "modify", ticketAction.GetMiner().GetModify(), "bits", ticketAction.GetMiner().GetBits(), "ticketId", ticketAction.GetMiner().GetTicketId(), "PrivHash", ticketAction.GetMiner().GetPrivHash())
modifies = append(modifies, ticketAction.GetMiner().GetModify()...)
bits += ticketAction.GetMiner().GetBits()
ticketIds += ticketAction.GetMiner().GetTicketId()
privHashs = append(privHashs, ticketAction.GetMiner().GetPrivHash()...)
vrfHashs = append(vrfHashs, ticketAction.GetMiner().GetVrfHash()...)
}
newmodify := fmt.Sprintf("%s:%s:%d:%s", string(modifies), ticketIds, bits, string(privHashs))
if len(vrfHashs) != 0 {
newmodify = fmt.Sprintf("%s:%x", newmodify, vrfHashs)
}
modify := common.Sha256([]byte(newmodify))
return &types.ReplyHash{Hash: modify}, nil
}
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", common.ToHex(blockHash), "blockNum", blockNum)
//根据blockHash,查询block,循环blockNum
for blockNum > 0 {
req := types.ReqHash{Hash: currHash}
tempBlock, err := ticket.GetAPI().GetBlockOverview(&req)
if err != nil {
return txActions, err
}
if tempBlock.Head.Height <= 0 {
return nil, nil
}
reqHashes.Hashes = append(reqHashes.Hashes, currHash)
currHash = tempBlock.Head.ParentHash
if tempBlock.Head.Height < 0 && blockNum > 1 {
return txActions, types.ErrBlockNotFound
}
if tempBlock.Head.Height <= 1 {
break
}
blockNum--
}
blockDetails, err := ticket.GetAPI().GetBlockByHashes(&reqHashes)
if err != nil {
tlog.Error("getTxActions", "blockHash", blockHash, "blockNum", blockNum, "err", err)
return txActions, err
}
cfg := ticket.GetAPI().GetConfig()
for _, block := range blockDetails.Items {
tlog.Debug("getTxActions", "blockHeight", block.Block.Height, "blockhash", common.ToHex(block.Block.Hash(cfg)))
ticketAction, err := ticket.getMinerTx(block.Block)
if err != nil {
return txActions, err
}
txActions = append(txActions, ticketAction)
}
return txActions, nil
}
func (ticket *Ticket) 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
}