OSDN Git Service

ece13868937ea8647e7c04c809dc877a1aa374ae
[bytom/bytom.git] / api / miner.go
1 package api
2
3 import (
4         "context"
5
6         "github.com/bytom/errors"
7         "github.com/bytom/protocol/bc"
8         "github.com/bytom/protocol/bc/types"
9 )
10
11 // BlockHeaderJSON struct provides support for get work in json format, when it also follows
12 // BlockHeader structure
13 type BlockHeaderJSON struct {
14         Version           uint64                 `json:"version"`             // The version of the block.
15         Height            uint64                 `json:"height"`              // The height of the block.
16         PreviousBlockHash bc.Hash                `json:"previous_block_hash"` // The hash of the previous block.
17         Timestamp         uint64                 `json:"timestamp"`           // The time of the block in seconds.
18         Nonce             uint64                 `json:"nonce"`               // Nonce used to generate the block.
19         Bits              uint64                 `json:"bits"`                // Difficulty target for the block.
20         BlockCommitment   *types.BlockCommitment `json:"block_commitment"`    //Block commitment
21 }
22
23 // getWork gets work in compressed protobuf format
24 func (a *API) getWork() Response {
25         work, err := a.GetWork()
26         if err != nil {
27                 return NewErrorResponse(err)
28         }
29         return NewSuccessResponse(work)
30 }
31
32 // getWorkJSON gets work in json format
33 func (a *API) getWorkJSON() Response {
34         work, err := a.GetWorkJSON()
35         if err != nil {
36                 return NewErrorResponse(err)
37         }
38         return NewSuccessResponse(work)
39 }
40
41 // SubmitWorkJSONReq is req struct for submit-work API
42 type SubmitWorkReq struct {
43         BlockHeader *types.BlockHeader `json:"block_header"`
44 }
45
46 // submitWork submits work in compressed protobuf format
47 func (a *API) submitWork(ctx context.Context, req *SubmitWorkReq) Response {
48         if err := a.SubmitWork(req.BlockHeader); err != nil {
49                 return NewErrorResponse(err)
50         }
51         return NewSuccessResponse(true)
52 }
53
54 // SubmitWorkJSONReq is req struct for submit-work-json API
55 type SubmitWorkJSONReq struct {
56         BlockHeader *BlockHeaderJSON `json:"block_header"`
57 }
58
59 // submitWorkJSON submits work in json format
60 func (a *API) submitWorkJSON(ctx context.Context, req *SubmitWorkJSONReq) Response {
61         bh := &types.BlockHeader{
62                 Version:           req.BlockHeader.Version,
63                 Height:            req.BlockHeader.Height,
64                 PreviousBlockHash: req.BlockHeader.PreviousBlockHash,
65                 Timestamp:         req.BlockHeader.Timestamp,
66                 Nonce:             req.BlockHeader.Nonce,
67                 Bits:              req.BlockHeader.Bits,
68                 BlockCommitment:   *req.BlockHeader.BlockCommitment,
69         }
70
71         if err := a.SubmitWork(bh); err != nil {
72                 return NewErrorResponse(err)
73         }
74         return NewSuccessResponse(true)
75 }
76
77 // GetWorkResp is resp struct for get-work API
78 type GetWorkResp struct {
79         BlockHeader *types.BlockHeader `json:"block_header"`
80         Seed        *bc.Hash           `json:"seed"`
81 }
82
83 // GetWork gets work in compressed protobuf format
84 func (a *API) GetWork() (*GetWorkResp, error) {
85         bh, err := a.miningPool.GetWork()
86         if err != nil {
87                 return nil, err
88         }
89
90         seed, err := a.chain.CalcNextSeed(&bh.PreviousBlockHash)
91         if err != nil {
92                 return nil, err
93         }
94
95         return &GetWorkResp{
96                 BlockHeader: bh,
97                 Seed:        seed,
98         }, nil
99 }
100
101 // GetWorkJSONResp is resp struct for get-work-json API
102 type GetWorkJSONResp struct {
103         BlockHeader *BlockHeaderJSON `json:"block_header"`
104         Seed        *bc.Hash         `json:"seed"`
105 }
106
107 // GetWorkJSON gets work in json format
108 func (a *API) GetWorkJSON() (*GetWorkJSONResp, error) {
109         bh, err := a.miningPool.GetWork()
110         if err != nil {
111                 return nil, err
112         }
113
114         seed, err := a.chain.CalcNextSeed(&bh.PreviousBlockHash)
115         if err != nil {
116                 return nil, err
117         }
118
119         return &GetWorkJSONResp{
120                 BlockHeader: &BlockHeaderJSON{
121                         Version:           bh.Version,
122                         Height:            bh.Height,
123                         PreviousBlockHash: bh.PreviousBlockHash,
124                         Timestamp:         bh.Timestamp,
125                         Nonce:             bh.Nonce,
126                         Bits:              bh.Bits,
127                         BlockCommitment:   &bh.BlockCommitment,
128                 },
129                 Seed: seed,
130         }, nil
131 }
132
133 // SubmitWork tries to submit work to the chain
134 func (a *API) SubmitWork(bh *types.BlockHeader) error {
135         return a.miningPool.SubmitWork(bh)
136 }
137
138 func (a *API) setMining(in struct {
139         IsMining bool `json:"is_mining"`
140 }) Response {
141         if in.IsMining {
142                 if _, err := a.wallet.AccountMgr.GetMiningAddress(); err != nil {
143                         return NewErrorResponse(errors.New("Mining address does not exist"))
144                 }
145                 return a.startMining()
146         }
147         return a.stopMining()
148 }
149
150 func (a *API) startMining() Response {
151         a.cpuMiner.Start()
152         if !a.IsMining() {
153                 return NewErrorResponse(errors.New("Failed to start mining"))
154         }
155         return NewSuccessResponse("")
156 }
157
158 func (a *API) stopMining() Response {
159         a.cpuMiner.Stop()
160         if a.IsMining() {
161                 return NewErrorResponse(errors.New("Failed to stop mining"))
162         }
163         return NewSuccessResponse("")
164 }