OSDN Git Service

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