6 "github.com/bytom/blockchain/query"
7 "github.com/bytom/consensus/difficulty"
8 chainjson "github.com/bytom/encoding/json"
9 "github.com/bytom/protocol/bc"
10 "github.com/bytom/protocol/bc/types"
13 // return best block hash
14 func (a *API) getBestBlockHash() Response {
15 blockHash := map[string]string{"block_hash": a.chain.BestBlockHash().String()}
16 return NewSuccessResponse(blockHash)
19 // return current block count
20 func (a *API) getBlockCount() Response {
21 blockHeight := map[string]uint64{"block_count": a.chain.BestBlockHeight()}
22 return NewSuccessResponse(blockHeight)
25 // BlockTx is the tx struct for getBlock func
27 ID bc.Hash `json:"id"`
28 Version uint64 `json:"version"`
29 Size uint64 `json:"size"`
30 TimeRange uint64 `json:"time_range"`
31 Inputs []*query.AnnotatedInput `json:"inputs"`
32 Outputs []*query.AnnotatedOutput `json:"outputs"`
33 StatusFail bool `json:"status_fail"`
36 // BlockReq is used to handle getBlock req
37 type BlockReq struct {
38 BlockHeight uint64 `json:"block_height"`
39 BlockHash chainjson.HexBytes `json:"block_hash"`
42 // GetBlockResp is the resp for getBlock api
43 type GetBlockResp struct {
44 Hash *bc.Hash `json:"hash"`
45 Size uint64 `json:"size"`
46 Version uint64 `json:"version"`
47 Height uint64 `json:"height"`
48 PreviousBlockHash *bc.Hash `json:"previous_block_hash"`
49 Timestamp uint64 `json:"timestamp"`
50 Nonce uint64 `json:"nonce"`
51 Bits uint64 `json:"bits"`
52 Difficulty string `json:"difficulty"`
53 TransactionsMerkleRoot *bc.Hash `json:"transaction_merkle_root"`
54 TransactionStatusHash *bc.Hash `json:"transaction_status_hash"`
55 Transactions []*BlockTx `json:"transactions"`
58 // return block by hash
59 func (a *API) getBlock(ins BlockReq) Response {
61 block := &types.Block{}
62 if len(ins.BlockHash) == 32 {
64 copy(b32[:], ins.BlockHash)
65 hash := bc.NewHash(b32)
66 block, err = a.chain.GetBlockByHash(&hash)
68 block, err = a.chain.GetBlockByHeight(ins.BlockHeight)
71 return NewErrorResponse(err)
74 blockHash := block.Hash()
75 txStatus, err := a.chain.GetTransactionStatus(&blockHash)
76 rawBlock, err := block.MarshalText()
78 return NewErrorResponse(err)
81 resp := &GetBlockResp{
83 Size: uint64(len(rawBlock)),
84 Version: block.Version,
86 PreviousBlockHash: &block.PreviousBlockHash,
87 Timestamp: block.Timestamp,
90 Difficulty: difficulty.CalcWork(block.Bits).String(),
91 TransactionsMerkleRoot: &block.TransactionsMerkleRoot,
92 TransactionStatusHash: &block.TransactionStatusHash,
93 Transactions: []*BlockTx{},
96 for i, orig := range block.Transactions {
99 Version: orig.Version,
100 Size: orig.SerializedSize,
101 TimeRange: orig.TimeRange,
102 Inputs: []*query.AnnotatedInput{},
103 Outputs: []*query.AnnotatedOutput{},
105 tx.StatusFail, err = txStatus.GetStatus(i)
107 NewSuccessResponse(resp)
110 for i := range orig.Inputs {
111 tx.Inputs = append(tx.Inputs, a.wallet.BuildAnnotatedInput(orig, uint32(i)))
113 for i := range orig.Outputs {
114 tx.Outputs = append(tx.Outputs, a.wallet.BuildAnnotatedOutput(orig, i))
116 resp.Transactions = append(resp.Transactions, tx)
118 return NewSuccessResponse(resp)
121 // GetBlockHeaderResp is resp struct for getBlockHeader API
122 type GetBlockHeaderResp struct {
123 BlockHeader *types.BlockHeader `json:"block_header"`
124 Reward uint64 `json:"reward"`
127 func (a *API) getBlockHeader(ins BlockReq) Response {
129 block := &types.Block{}
130 if len(ins.BlockHash) == 32 {
132 copy(b32[:], ins.BlockHash)
133 hash := bc.NewHash(b32)
134 block, err = a.chain.GetBlockByHash(&hash)
136 block, err = a.chain.GetBlockByHeight(ins.BlockHeight)
139 return NewErrorResponse(err)
142 resp := &GetBlockHeaderResp{
143 BlockHeader: &block.BlockHeader,
144 Reward: block.Transactions[0].Outputs[0].Amount,
146 return NewSuccessResponse(resp)
149 // GetDifficultyResp is resp struct for getDifficulty API
150 type GetDifficultyResp struct {
151 BlockHash *bc.Hash `json:"hash"`
152 BlockHeight uint64 `json:"height"`
153 Bits uint64 `json:"bits"`
154 Difficulty string `json:"difficulty"`
157 func (a *API) getDifficulty(ins *BlockReq) Response {
159 block := &types.Block{}
161 if len(ins.BlockHash) == 32 && ins.BlockHash != nil {
163 copy(b32[:], ins.BlockHash)
164 hash := bc.NewHash(b32)
165 block, err = a.chain.GetBlockByHash(&hash)
166 } else if ins.BlockHeight > 0 {
167 block, err = a.chain.GetBlockByHeight(ins.BlockHeight)
169 hash := a.chain.BestBlockHash()
170 block, err = a.chain.GetBlockByHash(hash)
174 return NewErrorResponse(err)
177 blockHash := block.Hash()
178 resp := &GetDifficultyResp{
179 BlockHash: &blockHash,
180 BlockHeight: block.Height,
182 Difficulty: difficulty.CalcWork(block.Bits).String(),
184 return NewSuccessResponse(resp)
187 // getHashRateResp is resp struct for getHashRate API
188 type getHashRateResp struct {
189 BlockHash *bc.Hash `json:"hash"`
190 BlockHeight uint64 `json:"height"`
191 HashRate uint64 `json:"hash_rate"`
194 func (a *API) getHashRate(ins BlockReq) Response {
196 block := &types.Block{}
198 if len(ins.BlockHash) == 32 && ins.BlockHash != nil {
200 copy(b32[:], ins.BlockHash)
201 hash := bc.NewHash(b32)
202 block, err = a.chain.GetBlockByHash(&hash)
203 } else if ins.BlockHeight > 0 {
204 block, err = a.chain.GetBlockByHeight(ins.BlockHeight)
206 hash := a.chain.BestBlockHash()
207 block, err = a.chain.GetBlockByHash(hash)
211 return NewErrorResponse(err)
214 preBlock, err := a.chain.GetBlockByHash(&block.PreviousBlockHash)
216 return NewErrorResponse(err)
219 diffTime := block.Timestamp - preBlock.Timestamp
220 hashCount := difficulty.CalcWork(block.Bits)
221 hashRate := new(big.Int).Div(hashCount, big.NewInt(int64(diffTime)))
223 blockHash := block.Hash()
224 resp := &getHashRateResp{
225 BlockHash: &blockHash,
226 BlockHeight: block.Height,
227 HashRate: hashRate.Uint64(),
229 return NewSuccessResponse(resp)