8 log "github.com/sirupsen/logrus"
10 "github.com/vapor/account"
11 "github.com/vapor/mining"
12 "github.com/vapor/protocol"
13 "github.com/vapor/protocol/bc"
14 "github.com/vapor/protocol/bc/types"
21 type submitBlockMsg struct {
22 blockHeader *types.BlockHeader
26 // MiningPool is the support struct for p2p mine pool
27 type MiningPool struct {
30 submitCh chan *submitBlockMsg
33 accountManager *account.Manager
34 txPool *protocol.TxPool
35 newBlockCh chan *bc.Hash
38 // NewMiningPool will create a new MiningPool
39 func NewMiningPool(c *protocol.Chain, accountManager *account.Manager, txPool *protocol.TxPool, newBlockCh chan *bc.Hash) *MiningPool {
41 submitCh: make(chan *submitBlockMsg, maxSubmitChSize),
43 accountManager: accountManager,
45 newBlockCh: newBlockCh,
52 // blockUpdater is the goroutine for keep update mining block
53 func (m *MiningPool) blockUpdater() {
56 case <-m.chain.BlockWaiter(m.chain.BestBlockHeight() + 1):
59 case submitMsg := <-m.submitCh:
60 err := m.submitWork(submitMsg.blockHeader)
64 submitMsg.reply <- err
69 // generateBlock generates a block template to mine
70 func (m *MiningPool) generateBlock() {
72 defer m.mutex.Unlock()
74 block, err := mining.NewBlockTemplate(m.chain, m.txPool, m.accountManager)
76 log.Errorf("miningpool: failed on create NewBlockTemplate: %v", err)
82 // GetWork will return a block header for p2p mining
83 func (m *MiningPool) GetWork() (*types.BlockHeader, error) {
86 defer m.mutex.RUnlock()
88 m.block.BlockHeader.Timestamp = uint64(time.Now().Unix())
89 bh := m.block.BlockHeader
92 return nil, errors.New("no block is ready for mining")
95 // SubmitWork will try to submit the result to the blockchain
96 func (m *MiningPool) SubmitWork(bh *types.BlockHeader) error {
97 reply := make(chan error, 1)
98 m.submitCh <- &submitBlockMsg{blockHeader: bh, reply: reply}
101 log.WithFields(log.Fields{"err": err, "height": bh.Height}).Warning("submitWork failed")
106 func (m *MiningPool) submitWork(bh *types.BlockHeader) error {
108 defer m.mutex.Unlock()
110 if m.block == nil || bh.PreviousBlockHash != m.block.PreviousBlockHash {
111 return errors.New("pending mining block has been changed")
114 //m.block.Nonce = bh.Nonce
115 m.block.Timestamp = bh.Timestamp
116 isOrphan, err := m.chain.ProcessBlock(m.block)
121 return errors.New("submit result is orphan")
124 blockHash := bh.Hash()
125 m.newBlockCh <- &blockHash