7 chainjson "github.com/vapor/encoding/json"
8 "github.com/vapor/errors"
9 "github.com/vapor/event"
10 "github.com/vapor/protocol/bc"
11 "github.com/vapor/protocol/bc/types"
14 // BlockHeaderJSON struct provides support for get work in json format, when it also follows
15 // BlockHeader structure
16 type BlockHeaderJSON struct {
17 Version uint64 `json:"version"` // The version of the block.
18 Height uint64 `json:"height"` // The height of the block.
19 PreviousBlockHash bc.Hash `json:"previous_block_hash"` // The hash of the previous block.
20 Timestamp uint64 `json:"timestamp"` // The time of the block in seconds.
21 Nonce uint64 `json:"nonce"` // Nonce used to generate the block.
22 Bits uint64 `json:"bits"` // Difficulty target for the block.
23 BlockCommitment *types.BlockCommitment `json:"block_commitment"` // Block commitment
26 type CoinbaseArbitrary struct {
27 Arbitrary chainjson.HexBytes `json:"arbitrary"`
30 func (a *API) getCoinbaseArbitrary() Response {
31 arbitrary := a.wallet.AccountMgr.GetCoinbaseArbitrary()
32 resp := &CoinbaseArbitrary{
35 return NewSuccessResponse(resp)
38 // setCoinbaseArbitrary add arbitary data to the reserved coinbase data.
39 // check function createCoinbaseTx in mining/mining.go for detail.
40 // arbitraryLenLimit is 107 and can be calculated by:
41 // maxHeight := ^uint64(0)
42 // reserved := append([]byte{0x00}, []byte(strconv.FormatUint(maxHeight, 10))...)
43 // arbitraryLenLimit := consensus.CoinbaseArbitrarySizeLimit - len(reserved)
44 func (a *API) setCoinbaseArbitrary(ctx context.Context, req CoinbaseArbitrary) Response {
45 arbitraryLenLimit := 107
46 if len(req.Arbitrary) > arbitraryLenLimit {
47 err := errors.New("Arbitrary exceeds limit: " + strconv.FormatUint(uint64(arbitraryLenLimit), 10))
48 return NewErrorResponse(err)
50 a.wallet.AccountMgr.SetCoinbaseArbitrary(req.Arbitrary)
51 return a.getCoinbaseArbitrary()
54 // getWork gets work in compressed protobuf format
55 func (a *API) getWork() Response {
56 work, err := a.GetWork()
58 return NewErrorResponse(err)
60 return NewSuccessResponse(work)
63 // getWorkJSON gets work in json format
64 func (a *API) getWorkJSON() Response {
65 work, err := a.GetWorkJSON()
67 return NewErrorResponse(err)
69 return NewSuccessResponse(work)
72 // SubmitBlockReq is req struct for submit-block API
73 type SubmitBlockReq struct {
74 Block *types.Block `json:"raw_block"`
77 // submitBlock trys to submit a raw block to the chain
78 func (a *API) submitBlock(ctx context.Context, req *SubmitBlockReq) Response {
79 isOrphan, err := a.chain.ProcessBlock(req.Block)
81 return NewErrorResponse(err)
85 return NewErrorResponse(errors.New("block submitted is orphan"))
88 if err = a.eventDispatcher.Post(event.NewMinedBlockEvent{Block: *req.Block}); err != nil {
89 return NewErrorResponse(err)
92 return NewSuccessResponse(true)
95 // SubmitWorkReq is req struct for submit-work API
96 type SubmitWorkReq struct {
97 BlockHeader *types.BlockHeader `json:"block_header"`
100 // submitWork submits work in compressed protobuf format
101 func (a *API) submitWork(ctx context.Context, req *SubmitWorkReq) Response {
102 if err := a.SubmitWork(req.BlockHeader); err != nil {
103 return NewErrorResponse(err)
105 return NewSuccessResponse(true)
108 // SubmitWorkJSONReq is req struct for submit-work-json API
109 type SubmitWorkJSONReq struct {
110 BlockHeader *BlockHeaderJSON `json:"block_header"`
113 // submitWorkJSON submits work in json format
114 func (a *API) submitWorkJSON(ctx context.Context, req *SubmitWorkJSONReq) Response {
115 bh := &types.BlockHeader{
116 Version: req.BlockHeader.Version,
117 Height: req.BlockHeader.Height,
118 PreviousBlockHash: req.BlockHeader.PreviousBlockHash,
119 Timestamp: req.BlockHeader.Timestamp,
120 Nonce: req.BlockHeader.Nonce,
121 Bits: req.BlockHeader.Bits,
122 BlockCommitment: *req.BlockHeader.BlockCommitment,
125 if err := a.SubmitWork(bh); err != nil {
126 return NewErrorResponse(err)
128 return NewSuccessResponse(true)
131 // GetWorkResp is resp struct for get-work API
132 type GetWorkResp struct {
133 BlockHeader *types.BlockHeader `json:"block_header"`
134 Seed *bc.Hash `json:"seed"`
137 // GetWork gets work in compressed protobuf format
138 func (a *API) GetWork() (*GetWorkResp, error) {
139 bh, err := a.miningPool.GetWork()
144 seed, err := a.chain.CalcNextSeed(&bh.PreviousBlockHash)
155 // GetWorkJSONResp is resp struct for get-work-json API
156 type GetWorkJSONResp struct {
157 BlockHeader *BlockHeaderJSON `json:"block_header"`
158 Seed *bc.Hash `json:"seed"`
161 // GetWorkJSON gets work in json format
162 func (a *API) GetWorkJSON() (*GetWorkJSONResp, error) {
163 bh, err := a.miningPool.GetWork()
168 seed, err := a.chain.CalcNextSeed(&bh.PreviousBlockHash)
173 return &GetWorkJSONResp{
174 BlockHeader: &BlockHeaderJSON{
177 PreviousBlockHash: bh.PreviousBlockHash,
178 Timestamp: bh.Timestamp,
181 BlockCommitment: &bh.BlockCommitment,
187 // SubmitWork tries to submit work to the chain
188 func (a *API) SubmitWork(bh *types.BlockHeader) error {
189 return a.miningPool.SubmitWork(bh)
192 func (a *API) setMining(in struct {
193 IsMining bool `json:"is_mining"`
196 if _, err := a.wallet.AccountMgr.GetMiningAddress(); err != nil {
197 return NewErrorResponse(errors.New("Mining address does not exist"))
199 return a.startMining()
201 return a.stopMining()
204 func (a *API) startMining() Response {
207 return NewErrorResponse(errors.New("Failed to start mining"))
209 return NewSuccessResponse("")
212 func (a *API) stopMining() Response {
215 return NewErrorResponse(errors.New("Failed to stop mining"))
217 return NewSuccessResponse("")